3 Copyright (C) 2013 sapier
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.
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.
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.
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 "scripting_mainmenu.h"
25 #include "gui/guiEngine.h"
26 #include "gui/guiMainMenu.h"
27 #include "gui/guiKeyChangeMenu.h"
28 #include "gui/guiPathSelectMenu.h"
32 #include "convert_json.h"
33 #include "content/content.h"
34 #include "content/subgames.h"
35 #include "mapgen/mapgen.h"
37 #include "client/client.h"
38 #include "client/renderingengine.h"
39 #include "network/networkprotocol.h"
40 #include "content/mod_configuration.h"
41 #include "threading/mutex_auto_lock.h"
42 #include "common/c_converter.h"
44 /******************************************************************************/
45 std::string
ModApiMainMenu::getTextData(lua_State
*L
, const std::string
&name
)
47 lua_getglobal(L
, "gamedata");
49 lua_getfield(L
, -1, name
.c_str());
54 return luaL_checkstring(L
, -1);
57 /******************************************************************************/
58 int ModApiMainMenu::getIntegerData(lua_State
*L
, const std::string
&name
, bool& valid
)
60 lua_getglobal(L
, "gamedata");
62 lua_getfield(L
, -1, name
.c_str());
64 if(lua_isnil(L
, -1)) {
70 return luaL_checkinteger(L
, -1);
73 /******************************************************************************/
74 int ModApiMainMenu::getBoolData(lua_State
*L
, const std::string
&name
, bool& valid
)
76 lua_getglobal(L
, "gamedata");
78 lua_getfield(L
, -1, name
.c_str());
80 if(lua_isnil(L
, -1)) {
86 return readParam
<bool>(L
, -1);
89 /******************************************************************************/
90 int ModApiMainMenu::l_update_formspec(lua_State
*L
)
92 GUIEngine
* engine
= getGuiEngine(L
);
93 sanity_check(engine
!= NULL
);
95 if (engine
->m_startgame
)
99 std::string
formspec(luaL_checkstring(L
, 1));
101 if (engine
->m_formspecgui
!= 0) {
102 engine
->m_formspecgui
->setForm(formspec
);
108 /******************************************************************************/
109 int ModApiMainMenu::l_set_formspec_prepend(lua_State
*L
)
111 GUIEngine
*engine
= getGuiEngine(L
);
112 sanity_check(engine
!= NULL
);
114 if (engine
->m_startgame
)
117 std::string
formspec(luaL_checkstring(L
, 1));
118 engine
->setFormspecPrepend(formspec
);
123 /******************************************************************************/
124 int ModApiMainMenu::l_start(lua_State
*L
)
126 GUIEngine
* engine
= getGuiEngine(L
);
127 sanity_check(engine
!= NULL
);
129 //update c++ gamedata from lua table
133 MainMenuData
*data
= engine
->m_data
;
135 data
->selected_world
= getIntegerData(L
, "selected_world",valid
) -1;
136 data
->simple_singleplayer_mode
= getBoolData(L
,"singleplayer",valid
);
137 data
->do_reconnect
= getBoolData(L
, "do_reconnect", valid
);
138 if (!data
->do_reconnect
) {
139 data
->name
= getTextData(L
,"playername");
140 data
->password
= getTextData(L
,"password");
141 data
->address
= getTextData(L
,"address");
142 data
->port
= getTextData(L
,"port");
144 const auto val
= getTextData(L
, "allow_login_or_register");
146 data
->allow_login_or_register
= ELoginRegister::Login
;
147 else if (val
== "register")
148 data
->allow_login_or_register
= ELoginRegister::Register
;
150 data
->allow_login_or_register
= ELoginRegister::Any
;
152 data
->serverdescription
= getTextData(L
,"serverdescription");
153 data
->servername
= getTextData(L
,"servername");
155 //close menu next time
156 engine
->m_startgame
= true;
160 /******************************************************************************/
161 int ModApiMainMenu::l_close(lua_State
*L
)
163 GUIEngine
* engine
= getGuiEngine(L
);
164 sanity_check(engine
!= NULL
);
166 engine
->m_kill
= true;
170 /******************************************************************************/
171 int ModApiMainMenu::l_set_background(lua_State
*L
)
173 GUIEngine
* engine
= getGuiEngine(L
);
174 sanity_check(engine
!= NULL
);
176 std::string
backgroundlevel(luaL_checkstring(L
, 1));
177 std::string
texturename(luaL_checkstring(L
, 2));
179 bool tile_image
= false;
181 unsigned int minsize
= 16;
183 if (!lua_isnone(L
, 3)) {
184 tile_image
= readParam
<bool>(L
, 3);
187 if (!lua_isnone(L
, 4)) {
188 minsize
= lua_tonumber(L
, 4);
191 if (backgroundlevel
== "background") {
192 retval
|= engine
->setTexture(TEX_LAYER_BACKGROUND
, texturename
,
193 tile_image
, minsize
);
196 if (backgroundlevel
== "overlay") {
197 retval
|= engine
->setTexture(TEX_LAYER_OVERLAY
, texturename
,
198 tile_image
, minsize
);
201 if (backgroundlevel
== "header") {
202 retval
|= engine
->setTexture(TEX_LAYER_HEADER
, texturename
,
203 tile_image
, minsize
);
206 if (backgroundlevel
== "footer") {
207 retval
|= engine
->setTexture(TEX_LAYER_FOOTER
, texturename
,
208 tile_image
, minsize
);
211 lua_pushboolean(L
,retval
);
215 /******************************************************************************/
216 int ModApiMainMenu::l_set_clouds(lua_State
*L
)
218 GUIEngine
* engine
= getGuiEngine(L
);
219 sanity_check(engine
!= NULL
);
221 bool value
= readParam
<bool>(L
,1);
223 engine
->m_clouds_enabled
= value
;
228 /******************************************************************************/
229 int ModApiMainMenu::l_get_textlist_index(lua_State
*L
)
231 // get_table_index accepts both tables and textlists
232 return l_get_table_index(L
);
235 /******************************************************************************/
236 int ModApiMainMenu::l_get_table_index(lua_State
*L
)
238 GUIEngine
* engine
= getGuiEngine(L
);
239 sanity_check(engine
!= NULL
);
241 std::string
tablename(luaL_checkstring(L
, 1));
242 GUITable
*table
= engine
->m_menu
->getTable(tablename
);
243 s32 selection
= table
? table
->getSelected() : 0;
246 lua_pushinteger(L
, selection
);
252 /******************************************************************************/
253 int ModApiMainMenu::l_get_worlds(lua_State
*L
)
255 std::vector
<WorldSpec
> worlds
= getAvailableWorlds();
258 int top
= lua_gettop(L
);
259 unsigned int index
= 1;
261 for (const WorldSpec
&world
: worlds
) {
262 lua_pushnumber(L
,index
);
265 int top_lvl2
= lua_gettop(L
);
267 lua_pushstring(L
,"path");
268 lua_pushstring(L
, world
.path
.c_str());
269 lua_settable(L
, top_lvl2
);
271 lua_pushstring(L
,"name");
272 lua_pushstring(L
, world
.name
.c_str());
273 lua_settable(L
, top_lvl2
);
275 lua_pushstring(L
,"gameid");
276 lua_pushstring(L
, world
.gameid
.c_str());
277 lua_settable(L
, top_lvl2
);
279 lua_settable(L
, top
);
285 /******************************************************************************/
286 int ModApiMainMenu::l_get_games(lua_State
*L
)
288 std::vector
<SubgameSpec
> games
= getAvailableGames();
291 int top
= lua_gettop(L
);
292 unsigned int index
= 1;
294 for (const SubgameSpec
&game
: games
) {
295 lua_pushnumber(L
, index
);
297 int top_lvl2
= lua_gettop(L
);
299 lua_pushstring(L
, "id");
300 lua_pushstring(L
, game
.id
.c_str());
301 lua_settable(L
, top_lvl2
);
303 lua_pushstring(L
, "path");
304 lua_pushstring(L
, game
.path
.c_str());
305 lua_settable(L
, top_lvl2
);
307 lua_pushstring(L
, "type");
308 lua_pushstring(L
, "game");
309 lua_settable(L
, top_lvl2
);
311 lua_pushstring(L
, "gamemods_path");
312 lua_pushstring(L
, game
.gamemods_path
.c_str());
313 lua_settable(L
, top_lvl2
);
315 lua_pushstring(L
, "name");
316 lua_pushstring(L
, game
.title
.c_str());
317 lua_settable(L
, top_lvl2
);
319 lua_pushstring(L
, "title");
320 lua_pushstring(L
, game
.title
.c_str());
321 lua_settable(L
, top_lvl2
);
323 lua_pushstring(L
, "author");
324 lua_pushstring(L
, game
.author
.c_str());
325 lua_settable(L
, top_lvl2
);
327 lua_pushstring(L
, "release");
328 lua_pushinteger(L
, game
.release
);
329 lua_settable(L
, top_lvl2
);
331 lua_pushstring(L
, "menuicon_path");
332 lua_pushstring(L
, game
.menuicon_path
.c_str());
333 lua_settable(L
, top_lvl2
);
335 lua_pushstring(L
, "addon_mods_paths");
337 int table2
= lua_gettop(L
);
338 int internal_index
= 1;
339 for (const auto &addon_mods_path
: game
.addon_mods_paths
) {
340 lua_pushnumber(L
, internal_index
);
341 lua_pushstring(L
, addon_mods_path
.second
.c_str());
342 lua_settable(L
, table2
);
345 lua_settable(L
, top_lvl2
);
346 lua_settable(L
, top
);
352 /******************************************************************************/
353 int ModApiMainMenu::l_get_content_info(lua_State
*L
)
355 std::string path
= luaL_checkstring(L
, 1);
359 parseContentInfo(spec
);
363 lua_pushstring(L
, spec
.name
.c_str());
364 lua_setfield(L
, -2, "name");
366 lua_pushstring(L
, spec
.title
.c_str());
367 lua_setfield(L
, -2, "title");
369 lua_pushstring(L
, spec
.type
.c_str());
370 lua_setfield(L
, -2, "type");
372 lua_pushstring(L
, spec
.author
.c_str());
373 lua_setfield(L
, -2, "author");
375 if (!spec
.title
.empty()) {
376 lua_pushstring(L
, spec
.title
.c_str());
377 lua_setfield(L
, -2, "title");
380 lua_pushinteger(L
, spec
.release
);
381 lua_setfield(L
, -2, "release");
383 lua_pushstring(L
, spec
.desc
.c_str());
384 lua_setfield(L
, -2, "description");
386 lua_pushstring(L
, spec
.path
.c_str());
387 lua_setfield(L
, -2, "path");
389 lua_pushstring(L
, spec
.textdomain
.c_str());
390 lua_setfield(L
, -2, "textdomain");
392 if (spec
.type
== "mod") {
395 parseModContents(spec
);
400 for (const auto &dep
: spec
.depends
) {
401 lua_pushstring(L
, dep
.c_str());
402 lua_rawseti(L
, -2, i
++);
404 lua_setfield(L
, -2, "depends");
406 // Optional Dependencies
409 for (const auto &dep
: spec
.optdepends
) {
410 lua_pushstring(L
, dep
.c_str());
411 lua_rawseti(L
, -2, i
++);
413 lua_setfield(L
, -2, "optional_depends");
419 /******************************************************************************/
420 int ModApiMainMenu::l_check_mod_configuration(lua_State
*L
)
422 std::string worldpath
= luaL_checkstring(L
, 1);
424 ModConfiguration modmgr
;
427 SubgameSpec gamespec
= findWorldSubgame(worldpath
);
428 modmgr
.addGameMods(gamespec
);
429 modmgr
.addModsInPath(worldpath
+ DIR_DELIM
+ "worldmods", "worldmods");
431 // Add user-configured mods
432 std::vector
<ModSpec
> modSpecs
;
434 luaL_checktype(L
, 2, LUA_TTABLE
);
437 while (lua_next(L
, 2)) {
438 // Ignore non-string keys
439 if (lua_type(L
, -2) != LUA_TSTRING
) {
441 "Unexpected non-string key in table passed to core.check_mod_configuration");
444 std::string modpath
= luaL_checkstring(L
, -1);
446 std::string virtual_path
= lua_tostring(L
, -1);
448 modSpecs
.emplace_back();
449 ModSpec
&spec
= modSpecs
.back();
450 spec
.name
= fs::GetFilenameFromPath(modpath
.c_str());
452 spec
.virtual_path
= virtual_path
;
453 if (!parseModContents(spec
)) {
454 throw LuaError("Not a mod!");
458 modmgr
.addMods(modSpecs
);
460 modmgr
.checkConflictsAndDeps();
461 } catch (const ModError
&err
) {
462 errorstream
<< err
.what() << std::endl
;
466 lua_pushboolean(L
, false);
467 lua_setfield(L
, -2, "is_consistent");
470 lua_setfield(L
, -2, "unsatisfied_mods");
473 lua_setfield(L
, -2, "satisfied_mods");
475 lua_pushstring(L
, err
.what());
476 lua_setfield(L
, -2, "error_message");
482 lua_pushboolean(L
, modmgr
.isConsistent());
483 lua_setfield(L
, -2, "is_consistent");
486 int top
= lua_gettop(L
);
487 unsigned int index
= 1;
488 for (const auto &spec
: modmgr
.getUnsatisfiedMods()) {
489 lua_pushnumber(L
, index
);
490 push_mod_spec(L
, spec
, true);
491 lua_settable(L
, top
);
495 lua_setfield(L
, -2, "unsatisfied_mods");
500 for (const auto &spec
: modmgr
.getMods()) {
501 lua_pushnumber(L
, index
);
502 push_mod_spec(L
, spec
, false);
503 lua_settable(L
, top
);
506 lua_setfield(L
, -2, "satisfied_mods");
510 /******************************************************************************/
511 int ModApiMainMenu::l_get_content_translation(lua_State
*L
)
513 GUIEngine
* engine
= getGuiEngine(L
);
514 sanity_check(engine
!= NULL
);
516 std::string path
= luaL_checkstring(L
, 1);
517 std::string domain
= luaL_checkstring(L
, 2);
518 std::string string
= luaL_checkstring(L
, 3);
519 std::string lang
= gettext("LANG_CODE");
520 if (lang
== "LANG_CODE")
523 auto *translations
= engine
->getContentTranslations(path
, domain
, lang
);
524 string
= wide_to_utf8(translate_string(utf8_to_wide(string
), translations
));
525 lua_pushstring(L
, string
.c_str());
529 /******************************************************************************/
530 int ModApiMainMenu::l_show_keys_menu(lua_State
*L
)
532 GUIEngine
*engine
= getGuiEngine(L
);
533 sanity_check(engine
!= NULL
);
535 GUIKeyChangeMenu
*kmenu
= new GUIKeyChangeMenu(
536 engine
->m_rendering_engine
->get_gui_env(),
539 engine
->m_menumanager
,
540 engine
->m_texture_source
.get());
545 /******************************************************************************/
546 int ModApiMainMenu::l_create_world(lua_State
*L
)
548 const char *name
= luaL_checkstring(L
, 1);
549 const char *gameid
= luaL_checkstring(L
, 2);
551 StringMap use_settings
;
552 luaL_checktype(L
, 3, LUA_TTABLE
);
554 while (lua_next(L
, 3) != 0) {
555 // key at index -2 and value at index -1
556 use_settings
[luaL_checkstring(L
, -2)] = luaL_checkstring(L
, -1);
561 std::string path
= porting::path_user
+ DIR_DELIM
563 + sanitizeDirName(name
, "world_");
565 std::vector
<SubgameSpec
> games
= getAvailableGames();
566 auto game_it
= std::find_if(games
.begin(), games
.end(), [gameid
] (const SubgameSpec
&spec
) {
567 return spec
.id
== gameid
;
569 if (game_it
== games
.end()) {
570 lua_pushstring(L
, "Game ID not found");
574 // Set the settings for world creation
575 // this is a bad hack but the best we have right now..
577 for (auto &it
: use_settings
) {
578 if (g_settings
->existsLocal(it
.first
))
579 backup
[it
.first
] = g_settings
->get(it
.first
);
580 g_settings
->set(it
.first
, it
.second
);
583 // Create world if it doesn't exist
585 loadGameConfAndInitWorld(path
, name
, *game_it
, true);
587 } catch (const BaseException
&e
) {
588 auto err
= std::string("Failed to initialize world: ") + e
.what();
589 lua_pushstring(L
, err
.c_str());
592 // Restore previous settings
593 for (auto &it
: use_settings
) {
594 auto it2
= backup
.find(it
.first
);
595 if (it2
== backup
.end())
596 g_settings
->remove(it
.first
); // wasn't set before
598 g_settings
->set(it
.first
, it2
->second
); // was set before
604 /******************************************************************************/
605 int ModApiMainMenu::l_delete_world(lua_State
*L
)
607 int world_id
= luaL_checkinteger(L
, 1) - 1;
608 std::vector
<WorldSpec
> worlds
= getAvailableWorlds();
609 if (world_id
< 0 || world_id
>= (int) worlds
.size()) {
610 lua_pushstring(L
, "Invalid world index");
613 const WorldSpec
&spec
= worlds
[world_id
];
614 if (!fs::RecursiveDelete(spec
.path
)) {
615 lua_pushstring(L
, "Failed to delete world");
621 /******************************************************************************/
622 int ModApiMainMenu::l_set_topleft_text(lua_State
*L
)
624 GUIEngine
* engine
= getGuiEngine(L
);
625 sanity_check(engine
!= NULL
);
629 if (!lua_isnone(L
,1) && !lua_isnil(L
,1))
630 text
= luaL_checkstring(L
, 1);
632 engine
->setTopleftText(text
);
636 /******************************************************************************/
637 int ModApiMainMenu::l_get_mapgen_names(lua_State
*L
)
639 std::vector
<const char *> names
;
640 bool include_hidden
= lua_isboolean(L
, 1) && readParam
<bool>(L
, 1);
641 Mapgen::getMapgenNames(&names
, include_hidden
);
644 for (size_t i
= 0; i
!= names
.size(); i
++) {
645 lua_pushstring(L
, names
[i
]);
646 lua_rawseti(L
, -2, i
+ 1);
653 /******************************************************************************/
654 int ModApiMainMenu::l_get_user_path(lua_State
*L
)
656 std::string path
= fs::RemoveRelativePathComponents(porting::path_user
);
657 lua_pushstring(L
, path
.c_str());
661 /******************************************************************************/
662 int ModApiMainMenu::l_get_modpath(lua_State
*L
)
664 std::string modpath
= fs::RemoveRelativePathComponents(
665 porting::path_user
+ DIR_DELIM
+ "mods" + DIR_DELIM
);
666 lua_pushstring(L
, modpath
.c_str());
670 /******************************************************************************/
671 int ModApiMainMenu::l_get_modpaths(lua_State
*L
)
675 ModApiMainMenu::l_get_modpath(L
);
676 lua_setfield(L
, -2, "mods");
678 for (const std::string
&component
: getEnvModPaths()) {
679 lua_pushstring(L
, component
.c_str());
680 lua_setfield(L
, -2, fs::AbsolutePath(component
).c_str());
685 /******************************************************************************/
686 int ModApiMainMenu::l_get_clientmodpath(lua_State
*L
)
688 std::string modpath
= fs::RemoveRelativePathComponents(
689 porting::path_user
+ DIR_DELIM
+ "clientmods" + DIR_DELIM
);
690 lua_pushstring(L
, modpath
.c_str());
694 /******************************************************************************/
695 int ModApiMainMenu::l_get_gamepath(lua_State
*L
)
697 std::string gamepath
= fs::RemoveRelativePathComponents(
698 porting::path_user
+ DIR_DELIM
+ "games" + DIR_DELIM
);
699 lua_pushstring(L
, gamepath
.c_str());
703 /******************************************************************************/
704 int ModApiMainMenu::l_get_texturepath(lua_State
*L
)
706 std::string gamepath
= fs::RemoveRelativePathComponents(
707 porting::path_user
+ DIR_DELIM
+ "textures");
708 lua_pushstring(L
, gamepath
.c_str());
712 /******************************************************************************/
713 int ModApiMainMenu::l_get_texturepath_share(lua_State
*L
)
715 std::string gamepath
= fs::RemoveRelativePathComponents(
716 porting::path_share
+ DIR_DELIM
+ "textures");
717 lua_pushstring(L
, gamepath
.c_str());
721 /******************************************************************************/
722 int ModApiMainMenu::l_get_cache_path(lua_State
*L
)
724 lua_pushstring(L
, fs::RemoveRelativePathComponents(porting::path_cache
).c_str());
728 /******************************************************************************/
729 int ModApiMainMenu::l_get_temp_path(lua_State
*L
)
731 if (lua_isnoneornil(L
, 1) || !lua_toboolean(L
, 1))
732 lua_pushstring(L
, fs::TempPath().c_str());
734 lua_pushstring(L
, fs::CreateTempFile().c_str());
738 /******************************************************************************/
739 int ModApiMainMenu::l_create_dir(lua_State
*L
) {
740 const char *path
= luaL_checkstring(L
, 1);
742 if (ModApiMainMenu::mayModifyPath(path
)) {
743 lua_pushboolean(L
, fs::CreateAllDirs(path
));
747 lua_pushboolean(L
, false);
751 /******************************************************************************/
752 int ModApiMainMenu::l_delete_dir(lua_State
*L
)
754 const char *path
= luaL_checkstring(L
, 1);
756 std::string absolute_path
= fs::RemoveRelativePathComponents(path
);
758 if (ModApiMainMenu::mayModifyPath(absolute_path
)) {
759 lua_pushboolean(L
, fs::RecursiveDelete(absolute_path
));
763 lua_pushboolean(L
, false);
767 /******************************************************************************/
768 int ModApiMainMenu::l_copy_dir(lua_State
*L
)
770 const char *source
= luaL_checkstring(L
, 1);
771 const char *destination
= luaL_checkstring(L
, 2);
773 bool keep_source
= true;
774 if (!lua_isnoneornil(L
, 3))
775 keep_source
= readParam
<bool>(L
, 3);
777 std::string abs_destination
= fs::RemoveRelativePathComponents(destination
);
778 std::string abs_source
= fs::RemoveRelativePathComponents(source
);
780 if (!ModApiMainMenu::mayModifyPath(abs_destination
) ||
781 (!keep_source
&& !ModApiMainMenu::mayModifyPath(abs_source
))) {
782 lua_pushboolean(L
, false);
788 retval
= fs::CopyDir(abs_source
, abs_destination
);
790 retval
= fs::MoveDir(abs_source
, abs_destination
);
791 lua_pushboolean(L
, retval
);
795 /******************************************************************************/
796 int ModApiMainMenu::l_is_dir(lua_State
*L
)
798 const char *path
= luaL_checkstring(L
, 1);
800 lua_pushboolean(L
, fs::IsDir(path
));
804 /******************************************************************************/
805 int ModApiMainMenu::l_extract_zip(lua_State
*L
)
807 const char *zipfile
= luaL_checkstring(L
, 1);
808 const char *destination
= luaL_checkstring(L
, 2);
810 std::string absolute_destination
= fs::RemoveRelativePathComponents(destination
);
812 if (ModApiMainMenu::mayModifyPath(absolute_destination
)) {
813 auto fs
= RenderingEngine::get_raw_device()->getFileSystem();
814 bool ok
= fs::extractZipFile(fs
, zipfile
, destination
);
815 lua_pushboolean(L
, ok
);
819 lua_pushboolean(L
,false);
823 /******************************************************************************/
824 int ModApiMainMenu::l_get_mainmenu_path(lua_State
*L
)
826 GUIEngine
* engine
= getGuiEngine(L
);
827 sanity_check(engine
!= NULL
);
829 lua_pushstring(L
,engine
->getScriptDir().c_str());
833 /******************************************************************************/
834 bool ModApiMainMenu::mayModifyPath(std::string path
)
836 path
= fs::RemoveRelativePathComponents(path
);
838 if (fs::PathStartsWith(path
, fs::TempPath()))
841 std::string path_user
= fs::RemoveRelativePathComponents(porting::path_user
);
843 if (fs::PathStartsWith(path
, path_user
+ DIR_DELIM
"client"))
845 if (fs::PathStartsWith(path
, path_user
+ DIR_DELIM
"games"))
847 if (fs::PathStartsWith(path
, path_user
+ DIR_DELIM
"mods"))
849 if (fs::PathStartsWith(path
, path_user
+ DIR_DELIM
"textures"))
851 if (fs::PathStartsWith(path
, path_user
+ DIR_DELIM
"worlds"))
854 if (fs::PathStartsWith(path
, fs::RemoveRelativePathComponents(porting::path_cache
)))
861 /******************************************************************************/
862 int ModApiMainMenu::l_may_modify_path(lua_State
*L
)
864 const char *target
= luaL_checkstring(L
, 1);
865 std::string absolute_destination
= fs::RemoveRelativePathComponents(target
);
866 lua_pushboolean(L
, ModApiMainMenu::mayModifyPath(absolute_destination
));
870 /******************************************************************************/
871 int ModApiMainMenu::l_show_path_select_dialog(lua_State
*L
)
873 GUIEngine
* engine
= getGuiEngine(L
);
874 sanity_check(engine
!= NULL
);
876 const char *formname
= luaL_checkstring(L
, 1);
877 const char *title
= luaL_checkstring(L
, 2);
878 bool is_file_select
= readParam
<bool>(L
, 3);
880 GUIFileSelectMenu
* fileOpenMenu
=
881 new GUIFileSelectMenu(engine
->m_rendering_engine
->get_gui_env(),
884 engine
->m_menumanager
,
888 fileOpenMenu
->setTextDest(engine
->m_buttonhandler
);
889 fileOpenMenu
->drop();
893 /******************************************************************************/
894 int ModApiMainMenu::l_download_file(lua_State
*L
)
896 const char *url
= luaL_checkstring(L
, 1);
897 const char *target
= luaL_checkstring(L
, 2);
900 std::string absolute_destination
= fs::RemoveRelativePathComponents(target
);
902 if (ModApiMainMenu::mayModifyPath(absolute_destination
)) {
903 if (GUIEngine::downloadFile(url
,absolute_destination
)) {
904 lua_pushboolean(L
,true);
908 errorstream
<< "DOWNLOAD denied: " << absolute_destination
909 << " isn't an allowed path" << std::endl
;
911 lua_pushboolean(L
,false);
915 /******************************************************************************/
916 int ModApiMainMenu::l_get_video_drivers(lua_State
*L
)
918 auto drivers
= RenderingEngine::getSupportedVideoDrivers();
921 for (u32 i
= 0; i
!= drivers
.size(); i
++) {
922 auto &info
= RenderingEngine::getVideoDriverInfo(drivers
[i
]);
925 lua_pushstring(L
, info
.name
.c_str());
926 lua_setfield(L
, -2, "name");
927 lua_pushstring(L
, info
.friendly_name
.c_str());
928 lua_setfield(L
, -2, "friendly_name");
930 lua_rawseti(L
, -2, i
+ 1);
936 /******************************************************************************/
937 int ModApiMainMenu::l_get_language(lua_State
*L
)
939 std::string lang
= gettext("LANG_CODE");
940 if (lang
== "LANG_CODE")
943 lua_pushstring(L
, lang
.c_str());
947 /******************************************************************************/
948 int ModApiMainMenu::l_gettext(lua_State
*L
)
950 const char *srctext
= luaL_checkstring(L
, 1);
951 const char *text
= *srctext
? gettext(srctext
) : "";
952 lua_pushstring(L
, text
);
957 /******************************************************************************/
958 int ModApiMainMenu::l_get_window_info(lua_State
*L
)
961 int top
= lua_gettop(L
);
963 auto info
= ClientDynamicInfo::getCurrent();
965 lua_pushstring(L
, "size");
966 push_v2u32(L
, info
.render_target_size
);
967 lua_settable(L
, top
);
969 lua_pushstring(L
, "max_formspec_size");
970 push_v2f(L
, info
.max_fs_size
);
971 lua_settable(L
, top
);
973 lua_pushstring(L
, "real_gui_scaling");
974 lua_pushnumber(L
, info
.real_gui_scaling
);
975 lua_settable(L
, top
);
977 lua_pushstring(L
, "real_hud_scaling");
978 lua_pushnumber(L
, info
.real_hud_scaling
);
979 lua_settable(L
, top
);
981 lua_pushstring(L
, "touch_controls");
982 lua_pushboolean(L
, info
.touch_controls
);
983 lua_settable(L
, top
);
988 /******************************************************************************/
989 int ModApiMainMenu::l_get_active_driver(lua_State
*L
)
991 auto drivertype
= RenderingEngine::get_video_driver()->getDriverType();
992 lua_pushstring(L
, RenderingEngine::getVideoDriverInfo(drivertype
).name
.c_str());
997 int ModApiMainMenu::l_get_active_renderer(lua_State
*L
)
999 lua_pushstring(L
, RenderingEngine::get_video_driver()->getName());
1003 /******************************************************************************/
1004 int ModApiMainMenu::l_get_active_irrlicht_device(lua_State
*L
)
1006 const char *device_name
= [] {
1007 switch (RenderingEngine::get_raw_device()->getType()) {
1008 case EIDT_WIN32
: return "WIN32";
1009 case EIDT_X11
: return "X11";
1010 case EIDT_OSX
: return "OSX";
1011 case EIDT_SDL
: return "SDL";
1012 case EIDT_ANDROID
: return "ANDROID";
1013 default: return "Unknown";
1016 lua_pushstring(L
, device_name
);
1020 /******************************************************************************/
1021 int ModApiMainMenu::l_get_min_supp_proto(lua_State
*L
)
1023 lua_pushinteger(L
, CLIENT_PROTOCOL_VERSION_MIN
);
1027 int ModApiMainMenu::l_get_max_supp_proto(lua_State
*L
)
1029 lua_pushinteger(L
, CLIENT_PROTOCOL_VERSION_MAX
);
1033 /******************************************************************************/
1034 int ModApiMainMenu::l_open_url(lua_State
*L
)
1036 std::string url
= luaL_checkstring(L
, 1);
1037 lua_pushboolean(L
, porting::open_url(url
));
1041 /******************************************************************************/
1042 int ModApiMainMenu::l_open_dir(lua_State
*L
)
1044 std::string path
= luaL_checkstring(L
, 1);
1045 lua_pushboolean(L
, porting::open_directory(path
));
1049 /******************************************************************************/
1050 int ModApiMainMenu::l_share_file(lua_State
*L
)
1053 std::string path
= luaL_checkstring(L
, 1);
1054 porting::shareFileAndroid(path
);
1055 lua_pushboolean(L
, true);
1057 lua_pushboolean(L
, false);
1062 /******************************************************************************/
1063 int ModApiMainMenu::l_do_async_callback(lua_State
*L
)
1065 MainMenuScripting
*script
= getScriptApi
<MainMenuScripting
>(L
);
1067 size_t func_length
, param_length
;
1068 const char* serialized_func_raw
= luaL_checklstring(L
, 1, &func_length
);
1069 const char* serialized_param_raw
= luaL_checklstring(L
, 2, ¶m_length
);
1071 sanity_check(serialized_func_raw
!= NULL
);
1072 sanity_check(serialized_param_raw
!= NULL
);
1074 u32 jobId
= script
->queueAsync(
1075 std::string(serialized_func_raw
, func_length
),
1076 std::string(serialized_param_raw
, param_length
));
1078 lua_pushinteger(L
, jobId
);
1083 /******************************************************************************/
1084 void ModApiMainMenu::Initialize(lua_State
*L
, int top
)
1086 API_FCT(update_formspec
);
1087 API_FCT(set_formspec_prepend
);
1088 API_FCT(set_clouds
);
1089 API_FCT(get_textlist_index
);
1090 API_FCT(get_table_index
);
1091 API_FCT(get_worlds
);
1093 API_FCT(get_content_info
);
1094 API_FCT(check_mod_configuration
);
1095 API_FCT(get_content_translation
);
1098 API_FCT(show_keys_menu
);
1099 API_FCT(create_world
);
1100 API_FCT(delete_world
);
1101 API_FCT(set_background
);
1102 API_FCT(set_topleft_text
);
1103 API_FCT(get_mapgen_names
);
1104 API_FCT(get_user_path
);
1105 API_FCT(get_modpath
);
1106 API_FCT(get_modpaths
);
1107 API_FCT(get_clientmodpath
);
1108 API_FCT(get_gamepath
);
1109 API_FCT(get_texturepath
);
1110 API_FCT(get_texturepath_share
);
1111 API_FCT(get_cache_path
);
1112 API_FCT(get_temp_path
);
1113 API_FCT(create_dir
);
1114 API_FCT(delete_dir
);
1117 API_FCT(extract_zip
);
1118 API_FCT(may_modify_path
);
1119 API_FCT(get_mainmenu_path
);
1120 API_FCT(show_path_select_dialog
);
1121 API_FCT(download_file
);
1122 API_FCT(get_language
);
1124 API_FCT(get_video_drivers
);
1125 API_FCT(get_window_info
);
1126 API_FCT(get_active_driver
);
1127 API_FCT(get_active_renderer
);
1128 API_FCT(get_active_irrlicht_device
);
1129 API_FCT(get_min_supp_proto
);
1130 API_FCT(get_max_supp_proto
);
1133 API_FCT(share_file
);
1134 API_FCT(do_async_callback
);
1137 /******************************************************************************/
1138 void ModApiMainMenu::InitializeAsync(lua_State
*L
, int top
)
1140 API_FCT(get_worlds
);
1142 API_FCT(get_mapgen_names
);
1143 API_FCT(get_user_path
);
1144 API_FCT(get_modpath
);
1145 API_FCT(get_modpaths
);
1146 API_FCT(get_clientmodpath
);
1147 API_FCT(get_gamepath
);
1148 API_FCT(get_texturepath
);
1149 API_FCT(get_texturepath_share
);
1150 API_FCT(get_cache_path
);
1151 API_FCT(get_temp_path
);
1152 API_FCT(create_dir
);
1153 API_FCT(delete_dir
);
1156 API_FCT(extract_zip
);
1157 API_FCT(may_modify_path
);
1158 API_FCT(download_file
);
1159 API_FCT(get_min_supp_proto
);
1160 API_FCT(get_max_supp_proto
);
1161 API_FCT(get_language
);