From e6380565236d6d963acf75538f1f8fec807190cc Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 9 Dec 2020 14:30:37 -0800 Subject: Allow configuring block disk and net compression. Change default disk level. --- builtin/settingtypes.txt | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'builtin') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index c9f16578c..251b6d868 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1048,6 +1048,13 @@ full_block_send_enable_min_time_from_building (Delay in sending blocks after bui # client number. max_packets_per_iteration (Max. packets per iteration) int 1024 +# ZLib compression level to use when sending mapblocks to the client. +# -1 - Zlib's default compression level +# 0 - no compresson, fastest +# 9 - best compression, slowest +# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method) +map_compression_level_net (Map Compression Level for Network Transfer) int -1 -1 9 + [*Game] # Default game when creating a new world. @@ -1240,6 +1247,13 @@ max_objects_per_block (Maximum objects per block) int 64 # See https://www.sqlite.org/pragma.html#pragma_synchronous sqlite_synchronous (Synchronous SQLite) enum 2 0,1,2 +# ZLib compression level to use when saving mapblocks to disk. +# -1 - Zlib's default compression level +# 0 - no compresson, fastest +# 9 - best compression, slowest +# (levels 1-3 use Zlib's "fast" method, 4-9 use the normal method) +map_compression_level_disk (Map Compression Level for Disk Storage) int 3 -1 9 + # Length of a server tick and the interval at which objects are generally updated over # network. dedicated_server_step (Dedicated server step) float 0.09 -- cgit v1.2.3 From 664f5ce9605b580b9500547fff1e54eac553f295 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 19 Dec 2020 13:27:15 +0000 Subject: Add open user data button to main menu (#10579) --- .../java/net/minetest/minetest/GameActivity.java | 4 +-- builtin/mainmenu/tab_credits.lua | 20 +++++++++++-- doc/menu_lua_api.txt | 7 +++++ src/porting.cpp | 35 +++++++++++++++++----- src/porting.h | 20 ++++++++++++- src/porting_android.cpp | 6 ++-- src/porting_android.h | 2 +- src/script/lua_api/l_mainmenu.cpp | 21 ++++++++++++- src/script/lua_api/l_mainmenu.h | 4 +++ 9 files changed, 100 insertions(+), 19 deletions(-) (limited to 'builtin') diff --git a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java index db126a2b9..38a388230 100644 --- a/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java +++ b/build/android/app/src/main/java/net/minetest/minetest/GameActivity.java @@ -142,8 +142,8 @@ public class GameActivity extends NativeActivity { return getResources().getDisplayMetrics().widthPixels; } - public void openURL(String url) { - Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url)); + public void openURI(String uri) { + Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(uri)); startActivity(browserIntent); } } diff --git a/builtin/mainmenu/tab_credits.lua b/builtin/mainmenu/tab_credits.lua index c2b7e503a..075274798 100644 --- a/builtin/mainmenu/tab_credits.lua +++ b/builtin/mainmenu/tab_credits.lua @@ -100,9 +100,10 @@ return { cbf_formspec = function(tabview, name, tabdata) local logofile = defaulttexturedir .. "logo.png" local version = core.get_version() - return "image[0.5,1;" .. core.formspec_escape(logofile) .. "]" .. - "label[0.5,2.8;" .. version.project .. " " .. version.string .. "]" .. - "button[0.5,3;2,2;homepage;minetest.net]" .. + local fs = "image[0.75,0.5;2.2,2.2;" .. core.formspec_escape(logofile) .. "]" .. + "style[label_button;border=false]" .. + "button[0.5,2;2.5,2;label_button;" .. version.project .. " " .. version.string .. "]" .. + "button[0.75,2.75;2,2;homepage;minetest.net]" .. "tablecolumns[color;text]" .. "tableoptions[background=#00000000;highlight=#00000000;border=false]" .. "table[3.5,-0.25;8.5,6.05;list_credits;" .. @@ -115,10 +116,23 @@ return { "#FFFF00," .. fgettext("Previous Contributors") .. ",," .. buildCreditList(previous_contributors) .. "," .. ";1]" + + if PLATFORM ~= "Android" then + fs = fs .. "tooltip[userdata;" .. + fgettext("Opens the directory that contains user-provided worlds, games, mods,\n" .. + "and texture packs in a file manager / explorer.") .. "]" + fs = fs .. "button[0,4.75;3.5,1;userdata;" .. fgettext("Open User Data Directory") .. "]" + end + + return fs end, cbf_button_handler = function(this, fields, name, tabdata) if fields.homepage then core.open_url("https://www.minetest.net") end + + if fields.userdata then + core.open_dir(core.get_user_path()) + end end, } diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 76bebe08b..8908552d5 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -43,10 +43,14 @@ core.get_max_supp_proto() core.open_url(url) ^ opens the URL in a web browser, returns false on failure. ^ Must begin with http:// or https:// +core.open_dir(path) +^ opens the path in the system file browser/explorer, returns false on failure. +^ Must be an existing directory. core.get_version() (possible in async calls) ^ returns current core version + Filesystem ---------- @@ -207,6 +211,9 @@ Content and Packages Content - an installed mod, modpack, game, or texture pack (txt) Package - content which is downloadable from the content db, may or may not be installed. +* core.get_user_path() (possible in async calls) + * returns path to global user data, + the directory that contains user-provided mods, worlds, games, and texture packs. * core.get_modpath() (possible in async calls) * returns path to global modpath * core.get_clientmodpath() (possible in async calls) diff --git a/src/porting.cpp b/src/porting.cpp index e7ed4e090..4c87bddee 100644 --- a/src/porting.cpp +++ b/src/porting.cpp @@ -719,29 +719,48 @@ int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...) return c; } -bool openURL(const std::string &url) +static bool open_uri(const std::string &uri) { - if ((url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") || - url.find_first_of("\r\n") != std::string::npos) { - errorstream << "Invalid url: " << url << std::endl; + if (uri.find_first_of("\r\n") != std::string::npos) { + errorstream << "Unable to open URI as it is invalid, contains new line: " << uri << std::endl; return false; } #if defined(_WIN32) - return (intptr_t)ShellExecuteA(NULL, NULL, url.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; + return (intptr_t)ShellExecuteA(NULL, NULL, uri.c_str(), NULL, NULL, SW_SHOWNORMAL) > 32; #elif defined(__ANDROID__) - openURLAndroid(url); + openURIAndroid(uri); return true; #elif defined(__APPLE__) - const char *argv[] = {"open", url.c_str(), NULL}; + const char *argv[] = {"open", uri.c_str(), NULL}; return posix_spawnp(NULL, "open", NULL, NULL, (char**)argv, (*_NSGetEnviron())) == 0; #else - const char *argv[] = {"xdg-open", url.c_str(), NULL}; + const char *argv[] = {"xdg-open", uri.c_str(), NULL}; return posix_spawnp(NULL, "xdg-open", NULL, NULL, (char**)argv, environ) == 0; #endif } +bool open_url(const std::string &url) +{ + if (url.substr(0, 7) != "http://" && url.substr(0, 8) != "https://") { + errorstream << "Unable to open browser as URL is missing schema: " << url << std::endl; + return false; + } + + return open_uri(url); +} + +bool open_directory(const std::string &path) +{ + if (!fs::IsDir(path)) { + errorstream << "Unable to open directory as it does not exist: " << path << std::endl; + return false; + } + + return open_uri(path); +} + // Load performance counter frequency only once at startup #ifdef _WIN32 diff --git a/src/porting.h b/src/porting.h index c7adf12a2..e4ebe36fd 100644 --- a/src/porting.h +++ b/src/porting.h @@ -332,7 +332,25 @@ void attachOrCreateConsole(); int mt_snprintf(char *buf, const size_t buf_size, const char *fmt, ...); -bool openURL(const std::string &url); +/** + * Opens URL in default web browser + * + * Must begin with http:// or https://, and not contain any new lines + * + * @param url The URL + * @return true on success, false on failure + */ +bool open_url(const std::string &url); + +/** + * Opens a directory in the default file manager + * + * The directory must exist. + * + * @param path Path to directory + * @return true on success, false on failure + */ +bool open_directory(const std::string &path); } // namespace porting diff --git a/src/porting_android.cpp b/src/porting_android.cpp index 41b521ec2..f5870c174 100644 --- a/src/porting_android.cpp +++ b/src/porting_android.cpp @@ -213,13 +213,13 @@ void showInputDialog(const std::string &acceptButton, const std::string &hint, jacceptButton, jhint, jcurrent, jeditType); } -void openURLAndroid(const std::string &url) +void openURIAndroid(const std::string &url) { - jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURL", + jmethodID url_open = jnienv->GetMethodID(nativeActivity, "openURI", "(Ljava/lang/String;)V"); FATAL_ERROR_IF(url_open == nullptr, - "porting::openURLAndroid unable to find java openURL method"); + "porting::openURIAndroid unable to find java openURI method"); jstring jurl = jnienv->NewStringUTF(url.c_str()); jnienv->CallVoidMethod(app_global->activity->clazz, url_open, jurl); diff --git a/src/porting_android.h b/src/porting_android.h index 6eb054041..239815922 100644 --- a/src/porting_android.h +++ b/src/porting_android.h @@ -58,7 +58,7 @@ void initializePathsAndroid(); void showInputDialog(const std::string &acceptButton, const std::string &hint, const std::string ¤t, int editType); -void openURLAndroid(const std::string &url); +void openURIAndroid(const std::string &url); /** * WORKAROUND for not working callbacks from java -> c++ diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 0aa2760e9..0b0b2de3b 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -686,6 +686,14 @@ int ModApiMainMenu::l_get_mapgen_names(lua_State *L) } +/******************************************************************************/ +int ModApiMainMenu::l_get_user_path(lua_State *L) +{ + std::string path = fs::RemoveRelativePathComponents(porting::path_user); + lua_pushstring(L, path.c_str()); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_get_modpath(lua_State *L) { @@ -1067,7 +1075,15 @@ int ModApiMainMenu::l_get_max_supp_proto(lua_State *L) int ModApiMainMenu::l_open_url(lua_State *L) { std::string url = luaL_checkstring(L, 1); - lua_pushboolean(L, porting::openURL(url)); + lua_pushboolean(L, porting::open_url(url)); + return 1; +} + +/******************************************************************************/ +int ModApiMainMenu::l_open_dir(lua_State *L) +{ + std::string path = luaL_checkstring(L, 1); + lua_pushboolean(L, porting::open_directory(path)); return 1; } @@ -1113,6 +1129,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(set_background); API_FCT(set_topleft_text); API_FCT(get_mapgen_names); + API_FCT(get_user_path); API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); @@ -1134,6 +1151,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_min_supp_proto); API_FCT(get_max_supp_proto); API_FCT(open_url); + API_FCT(open_dir); API_FCT(do_async_callback); } @@ -1144,6 +1162,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(get_games); API_FCT(get_favorites); API_FCT(get_mapgen_names); + API_FCT(get_user_path); API_FCT(get_modpath); API_FCT(get_clientmodpath); API_FCT(get_gamepath); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 5a16b3bfe..faa2bf273 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -112,6 +112,8 @@ private: static int l_get_mainmenu_path(lua_State *L); + static int l_get_user_path(lua_State *L); + static int l_get_modpath(lua_State *L); static int l_get_clientmodpath(lua_State *L); @@ -148,6 +150,8 @@ private: // other static int l_open_url(lua_State *L); + static int l_open_dir(lua_State *L); + // async static int l_do_async_callback(lua_State *L); -- cgit v1.2.3 From 5066fe75830b98f592717b593099a757337c952d Mon Sep 17 00:00:00 2001 From: Andrey Date: Sun, 20 Dec 2020 00:00:20 +0300 Subject: MainMenu: Add clear button and icon for search input (#10363) --- LICENSE.txt | 2 ++ builtin/mainmenu/dlg_contentstore.lua | 11 +++++++++-- builtin/mainmenu/tab_online.lua | 9 ++++++++- textures/base/pack/clear.png | Bin 0 -> 708 bytes textures/base/pack/search.png | Bin 0 -> 1908 bytes 5 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 textures/base/pack/clear.png create mode 100644 textures/base/pack/search.png (limited to 'builtin') diff --git a/LICENSE.txt b/LICENSE.txt index f5c51833b..9fbd23723 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -23,6 +23,8 @@ paramat: textures/base/pack/menu_header.png textures/base/pack/next_icon.png textures/base/pack/prev_icon.png + textures/base/pack/clear.png + textures/base/pack/search.png rubenwardy, paramat: textures/base/pack/start_icon.png diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 6525f6013..7a96df2a5 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -340,7 +340,6 @@ function store.get_formspec(dlgdata) local W = 15.75 local H = 9.5 - local formspec if #store.packages_full > 0 then formspec = { @@ -353,7 +352,8 @@ function store.get_formspec(dlgdata) "container[0.375,0.375]", "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]", "field_close_on_enter[search_string;false]", - "button[7.225,0;2,0.8;search;", fgettext("Search"), "]", + "image_button[7.3,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "search.png"), ";search;]", + "image_button[8.125,0;0.8,0.8;", core.formspec_escape(defaulttexturedir .. "clear.png"), ";clear;]", "dropdown[9.6,0;2.4,0.8;type;", table.concat(filter_types_titles, ","), ";", filter_type, "]", "container_end[]", @@ -504,6 +504,13 @@ function store.handle_submit(this, fields) return true end + if fields.clear then + search_string = "" + cur_page = 1 + store.filter_packages("") + return true + end + if fields.back then this:delete() return true diff --git a/builtin/mainmenu/tab_online.lua b/builtin/mainmenu/tab_online.lua index 7985fd84a..8f1341161 100644 --- a/builtin/mainmenu/tab_online.lua +++ b/builtin/mainmenu/tab_online.lua @@ -34,7 +34,8 @@ local function get_formspec(tabview, name, tabdata) local retval = -- Search "field[0.15,0.075;5.91,1;te_search;;" .. core.formspec_escape(tabdata.search_for) .. "]" .. - "button[5.62,-0.25;1.5,1;btn_mp_search;" .. fgettext("Search") .. "]" .. + "image_button[5.63,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "search.png") .. ";btn_mp_search;]" .. + "image_button[6.3,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "clear.png") .. ";btn_mp_clear;]" .. "image_button[6.97,-.165;.83,.83;" .. core.formspec_escape(defaulttexturedir .. "refresh.png") .. ";btn_mp_refresh;]" .. @@ -243,6 +244,12 @@ local function main_button_handler(tabview, fields, name, tabdata) return true end + if fields.btn_mp_clear then + tabdata.search_for = "" + menudata.search_result = nil + return true + end + if fields.btn_mp_search or fields.key_enter_field == "te_search" then tabdata.fav_selected = 1 local input = fields.te_search:lower() diff --git a/textures/base/pack/clear.png b/textures/base/pack/clear.png new file mode 100644 index 000000000..9244264ad Binary files /dev/null and b/textures/base/pack/clear.png differ diff --git a/textures/base/pack/search.png b/textures/base/pack/search.png new file mode 100644 index 000000000..aace8044a Binary files /dev/null and b/textures/base/pack/search.png differ -- cgit v1.2.3 From af22dd86e3867a35e9e5ab911faa6e1e7671729d Mon Sep 17 00:00:00 2001 From: Markus Date: Sat, 19 Dec 2020 22:01:05 +0100 Subject: Fix some more joystick issues (#10624) --- builtin/settingtypes.txt | 3 +++ minetest.conf.example | 3 +++ src/client/game.cpp | 4 +-- src/client/inputhandler.h | 2 +- src/client/joystick_controller.cpp | 50 ++++++++++++++++++++------------------ src/client/joystick_controller.h | 38 +++++++++++++---------------- src/defaultsettings.cpp | 1 + 7 files changed, 53 insertions(+), 48 deletions(-) (limited to 'builtin') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 251b6d868..7060a0b6e 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -152,6 +152,9 @@ joystick_type (Joystick type) enum auto auto,generic,xbox # when holding down a joystick button combination. repeat_joystick_button_time (Joystick button repetition interval) float 0.17 0.001 +# The deadzone of the joystick +joystick_deadzone (Joystick deadzone) int 2048 + # The sensitivity of the joystick axes for moving the # ingame view frustum around. joystick_frustum_sensitivity (Joystick frustum sensitivity) float 170 diff --git a/minetest.conf.example b/minetest.conf.example index 6b315b6ea..086339037 100644 --- a/minetest.conf.example +++ b/minetest.conf.example @@ -129,6 +129,9 @@ # type: float min: 0.001 # repeat_joystick_button_time = 0.17 +# The deadzone of the joystick +# joystick_deadzone = 2048 + # The sensitivity of the joystick axes for moving the # ingame view frustum around. # type: float diff --git a/src/client/game.cpp b/src/client/game.cpp index fd4d09394..6151d2aa6 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3139,8 +3139,8 @@ void Game::processPlayerInteraction(f32 dtime, bool show_hud, bool show_debug) wasKeyDown(KeyType::DIG); wasKeyDown(KeyType::PLACE); - input->joystick.clearWasKeyDown(KeyType::DIG); - input->joystick.clearWasKeyDown(KeyType::PLACE); + input->joystick.clearWasKeyPressed(KeyType::DIG); + input->joystick.clearWasKeyPressed(KeyType::PLACE); input->joystick.clearWasKeyReleased(KeyType::DIG); input->joystick.clearWasKeyReleased(KeyType::PLACE); diff --git a/src/client/inputhandler.h b/src/client/inputhandler.h index def147a82..7487bbdc7 100644 --- a/src/client/inputhandler.h +++ b/src/client/inputhandler.h @@ -279,7 +279,7 @@ public: } virtual bool wasKeyPressed(GameKeyType k) { - return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyReleased(k); + return m_receiver->WasKeyPressed(keycache.key[k]) || joystick.wasKeyPressed(k); } virtual bool wasKeyReleased(GameKeyType k) { diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp index 742115046..f61ae4ae6 100644 --- a/src/client/joystick_controller.cpp +++ b/src/client/joystick_controller.cpp @@ -37,7 +37,7 @@ bool JoystickAxisCmb::isTriggered(const irr::SEvent::SJoystickEvent &ev) const { s16 ax_val = ev.Axis[axis_to_compare]; - return (ax_val * direction < 0) && (thresh * direction > ax_val * direction); + return (ax_val * direction < -thresh); } // spares many characters @@ -48,7 +48,7 @@ JoystickLayout create_default_layout() { JoystickLayout jlo; - jlo.axes_dead_border = 1024; + jlo.axes_deadzone = g_settings->getU16("joystick_deadzone"); const JoystickAxisLayout axes[JA_COUNT] = { {0, 1}, // JA_SIDEWARD_MOVE @@ -93,14 +93,14 @@ JoystickLayout create_default_layout() // Now about the buttons simulated by the axes // Movement buttons, important for vessels - JLO_A_PB(KeyType::FORWARD, 1, 1, 1024); - JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024); - JLO_A_PB(KeyType::LEFT, 0, 1, 1024); - JLO_A_PB(KeyType::RIGHT, 0, -1, 1024); + JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone); // Scroll buttons - JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, 1024); - JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, 1024); + JLO_A_PB(KeyType::HOTBAR_PREV, 2, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::HOTBAR_NEXT, 5, -1, jlo.axes_deadzone); return jlo; } @@ -109,7 +109,7 @@ JoystickLayout create_xbox_layout() { JoystickLayout jlo; - jlo.axes_dead_border = 7000; + jlo.axes_deadzone = 7000; const JoystickAxisLayout axes[JA_COUNT] = { {0, 1}, // JA_SIDEWARD_MOVE @@ -146,10 +146,10 @@ JoystickLayout create_xbox_layout() JLO_B_PB(KeyType::FREEMOVE, 1 << 16, 1 << 16); // down // Movement buttons, important for vessels - JLO_A_PB(KeyType::FORWARD, 1, 1, 1024); - JLO_A_PB(KeyType::BACKWARD, 1, -1, 1024); - JLO_A_PB(KeyType::LEFT, 0, 1, 1024); - JLO_A_PB(KeyType::RIGHT, 0, -1, 1024); + JLO_A_PB(KeyType::FORWARD, 1, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::BACKWARD, 1, -1, jlo.axes_deadzone); + JLO_A_PB(KeyType::LEFT, 0, 1, jlo.axes_deadzone); + JLO_A_PB(KeyType::RIGHT, 0, -1, jlo.axes_deadzone); return jlo; } @@ -219,16 +219,19 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev) for (size_t i = 0; i < KeyType::INTERNAL_ENUM_COUNT; i++) { if (keys_pressed[i]) { - if (!m_past_pressed_keys[i] && + if (!m_past_keys_pressed[i] && m_past_pressed_time[i] < m_internal_time - doubling_dtime) { - m_past_pressed_keys[i] = true; + m_past_keys_pressed[i] = true; m_past_pressed_time[i] = m_internal_time; } - } else if (m_pressed_keys[i]) { - m_past_released_keys[i] = true; + } else if (m_keys_down[i]) { + m_keys_released[i] = true; } - m_pressed_keys[i] = keys_pressed[i]; + if (keys_pressed[i] && !(m_keys_down[i])) + m_keys_pressed[i] = true; + + m_keys_down[i] = keys_pressed[i]; } for (size_t i = 0; i < JA_COUNT; i++) { @@ -236,23 +239,22 @@ bool JoystickController::handleEvent(const irr::SEvent::SJoystickEvent &ev) m_axes_vals[i] = ax_la.invert * ev.Axis[ax_la.axis_id]; } - return true; } void JoystickController::clear() { - m_pressed_keys.reset(); - m_past_pressed_keys.reset(); - m_past_released_keys.reset(); + m_keys_pressed.reset(); + m_keys_down.reset(); + m_past_keys_pressed.reset(); + m_keys_released.reset(); memset(m_axes_vals, 0, sizeof(m_axes_vals)); } s16 JoystickController::getAxisWithoutDead(JoystickAxis axis) { s16 v = m_axes_vals[axis]; - if (((v > 0) && (v < m_layout.axes_dead_border)) || - ((v < 0) && (v > -m_layout.axes_dead_border))) + if (abs(v) < m_layout.axes_deadzone) return 0; return v; } diff --git a/src/client/joystick_controller.h b/src/client/joystick_controller.h index 7baacd81b..3f361e4ef 100644 --- a/src/client/joystick_controller.h +++ b/src/client/joystick_controller.h @@ -96,7 +96,7 @@ struct JoystickLayout { std::vector button_keys; std::vector axis_keys; JoystickAxisLayout axes[JA_COUNT]; - s16 axes_dead_border; + s16 axes_deadzone; }; class JoystickController { @@ -111,37 +111,32 @@ public: bool wasKeyDown(GameKeyType b) { - bool r = m_past_pressed_keys[b]; - m_past_pressed_keys[b] = false; + bool r = m_past_keys_pressed[b]; + m_past_keys_pressed[b] = false; return r; } - bool getWasKeyDown(GameKeyType b) + + bool wasKeyReleased(GameKeyType b) { - return m_past_pressed_keys[b]; + return m_keys_released[b]; } - void clearWasKeyDown(GameKeyType b) + void clearWasKeyReleased(GameKeyType b) { - m_past_pressed_keys[b] = false; + m_keys_released[b] = false; } - bool wasKeyReleased(GameKeyType b) + bool wasKeyPressed(GameKeyType b) { - bool r = m_past_released_keys[b]; - m_past_released_keys[b] = false; - return r; - } - bool getWasKeyReleased(GameKeyType b) - { - return m_past_pressed_keys[b]; + return m_keys_pressed[b]; } - void clearWasKeyReleased(GameKeyType b) + void clearWasKeyPressed(GameKeyType b) { - m_past_pressed_keys[b] = false; + m_keys_pressed[b] = false; } bool isKeyDown(GameKeyType b) { - return m_pressed_keys[b]; + return m_keys_down[b]; } s16 getAxis(JoystickAxis axis) @@ -162,12 +157,13 @@ private: u8 m_joystick_id = 0; - std::bitset m_pressed_keys; + std::bitset m_keys_down; + std::bitset m_keys_pressed; f32 m_internal_time; f32 m_past_pressed_time[KeyType::INTERNAL_ENUM_COUNT]; - std::bitset m_past_pressed_keys; - std::bitset m_past_released_keys; + std::bitset m_past_keys_pressed; + std::bitset m_keys_released; }; diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e13977fe3..e8fb18e05 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -279,6 +279,7 @@ void set_default_settings(Settings *settings) settings->setDefault("joystick_type", ""); settings->setDefault("repeat_joystick_button_time", "0.17"); settings->setDefault("joystick_frustum_sensitivity", "170"); + settings->setDefault("joystick_deadzone", "2048"); // Main menu settings->setDefault("main_menu_path", ""); -- cgit v1.2.3 From 535557cc2e972c555bc5a294b95f2c2974b81eea Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Tue, 22 Dec 2020 14:54:27 +0100 Subject: Fix fallnode rotation of wallmounted nodebox/mesh (#10643) --- builtin/game/falling.lua | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'builtin') diff --git a/builtin/game/falling.lua b/builtin/game/falling.lua index f489ea702..057d0d0ed 100644 --- a/builtin/game/falling.lua +++ b/builtin/game/falling.lua @@ -152,8 +152,8 @@ core.register_entity(":__builtin:falling_node", { else self.object:set_yaw(-math.pi*0.25) end - elseif (node.param2 ~= 0 and (def.wield_image == "" - or def.wield_image == nil)) + elseif ((node.param2 ~= 0 or def.drawtype == "nodebox" or def.drawtype == "mesh") + and (def.wield_image == "" or def.wield_image == nil)) or def.drawtype == "signlike" or def.drawtype == "mesh" or def.drawtype == "normal" @@ -168,16 +168,30 @@ core.register_entity(":__builtin:falling_node", { elseif (def.paramtype2 == "wallmounted" or def.paramtype2 == "colorwallmounted") then local rot = node.param2 % 8 local pitch, yaw, roll = 0, 0, 0 - if rot == 1 then - pitch, yaw = math.pi, math.pi - elseif rot == 2 then - pitch, yaw = math.pi/2, math.pi/2 - elseif rot == 3 then - pitch, yaw = math.pi/2, -math.pi/2 - elseif rot == 4 then - pitch, yaw = math.pi/2, math.pi - elseif rot == 5 then - pitch, yaw = math.pi/2, 0 + if def.drawtype == "nodebox" or def.drawtype == "mesh" then + if rot == 0 then + pitch, yaw = math.pi/2, 0 + elseif rot == 1 then + pitch, yaw = -math.pi/2, math.pi + elseif rot == 2 then + pitch, yaw = 0, math.pi/2 + elseif rot == 3 then + pitch, yaw = 0, -math.pi/2 + elseif rot == 4 then + pitch, yaw = 0, math.pi + end + else + if rot == 1 then + pitch, yaw = math.pi, math.pi + elseif rot == 2 then + pitch, yaw = math.pi/2, math.pi/2 + elseif rot == 3 then + pitch, yaw = math.pi/2, -math.pi/2 + elseif rot == 4 then + pitch, yaw = math.pi/2, math.pi + elseif rot == 5 then + pitch, yaw = math.pi/2, 0 + end end if def.drawtype == "signlike" then pitch = pitch - math.pi/2 @@ -186,7 +200,7 @@ core.register_entity(":__builtin:falling_node", { elseif rot == 1 then yaw = yaw - math.pi/2 end - elseif def.drawtype == "mesh" or def.drawtype == "normal" then + elseif def.drawtype == "mesh" or def.drawtype == "normal" or def.drawtype == "nodebox" then if rot >= 0 and rot <= 1 then roll = roll + math.pi else -- cgit v1.2.3 From d2bbf13dfe61c48c1051ab5bd8b2b0e97ad7599e Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 23 Dec 2020 14:42:18 +0000 Subject: Add dependency resolution to ContentDB (#9997) --- builtin/mainmenu/dlg_contentstore.lua | 301 +++++++++++++++++++++++++++++++++- builtin/mainmenu/dlg_create_world.lua | 2 +- builtin/mainmenu/init.lua | 1 + builtin/settingtypes.txt | 1 + 4 files changed, 300 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 7a96df2a5..548bae67e 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -159,6 +159,290 @@ local function queue_download(package) end end +local function get_raw_dependencies(package) + if package.raw_deps then + return package.raw_deps + end + + local url_fmt = "/api/packages/%s/dependencies/?only_hard=1&protocol_version=%s&engine_version=%s" + local version = core.get_version() + local base_url = core.settings:get("contentdb_url") + local url = base_url .. url_fmt:format(package.id, core.get_max_supp_proto(), version.string) + + local response = http.fetch_sync({ url = url }) + if not response.succeeded then + return + end + + local data = core.parse_json(response.data) or {} + + local content_lookup = {} + for _, pkg in pairs(store.packages_full) do + content_lookup[pkg.id] = pkg + end + + for id, raw_deps in pairs(data) do + local package2 = content_lookup[id:lower()] + if package2 and not package2.raw_deps then + package2.raw_deps = raw_deps + + for _, dep in pairs(raw_deps) do + local packages = {} + for i=1, #dep.packages do + packages[#packages + 1] = content_lookup[dep.packages[i]:lower()] + end + dep.packages = packages + end + end + end + + return package.raw_deps +end + +local function has_hard_deps(raw_deps) + for i=1, #raw_deps do + if not raw_deps[i].is_optional then + return true + end + end + + return false +end + +-- Recursively resolve dependencies, given the installed mods +local function resolve_dependencies_2(raw_deps, installed_mods, out) + local function resolve_dep(dep) + -- Check whether it's already installed + if installed_mods[dep.name] then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = true, + } + end + + -- Find exact name matches + local fallback + for _, package in pairs(dep.packages) do + if package.type ~= "game" then + if package.name == dep.name then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + package = package, + } + elseif not fallback then + fallback = package + end + end + end + + -- Otherwise, find the first mod that fulfils it + if fallback then + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + package = fallback, + } + end + + return { + is_optional = dep.is_optional, + name = dep.name, + installed = false, + } + end + + for _, dep in pairs(raw_deps) do + if not dep.is_optional and not out[dep.name] then + local result = resolve_dep(dep) + out[dep.name] = result + if result and result.package and not result.installed then + local raw_deps2 = get_raw_dependencies(result.package) + if raw_deps2 then + resolve_dependencies_2(raw_deps2, installed_mods, out) + end + end + end + end + + return true +end + +-- Resolve dependencies for a package, calls the recursive version. +local function resolve_dependencies(raw_deps, game) + assert(game) + + local installed_mods = {} + + local mods = {} + pkgmgr.get_game_mods(game, mods) + for _, mod in pairs(mods) do + installed_mods[mod.name] = true + end + + for _, mod in pairs(pkgmgr.global_mods:get_list()) do + installed_mods[mod.name] = true + end + + local out = {} + if not resolve_dependencies_2(raw_deps, installed_mods, out) then + return nil + end + + local retval = {} + for _, dep in pairs(out) do + retval[#retval + 1] = dep + end + + table.sort(retval, function(a, b) + return a.name < b.name + end) + + return retval +end + +local install_dialog = {} +function install_dialog.get_formspec() + local package = install_dialog.package + local raw_deps = install_dialog.raw_deps + local will_install_deps = install_dialog.will_install_deps + + local selected_game_idx = 1 + local selected_gameid = core.settings:get("menu_last_game") + local games = table.copy(pkgmgr.games) + for i=1, #games do + if selected_gameid and games[i].id == selected_gameid then + selected_game_idx = i + end + + games[i] = minetest.formspec_escape(games[i].name) + end + + local selected_game = pkgmgr.games[selected_game_idx] + local deps_to_install = 0 + local deps_not_found = 0 + + install_dialog.dependencies = resolve_dependencies(raw_deps, selected_game) + local formatted_deps = {} + for _, dep in pairs(install_dialog.dependencies) do + formatted_deps[#formatted_deps + 1] = "#fff" + formatted_deps[#formatted_deps + 1] = minetest.formspec_escape(dep.name) + if dep.installed then + formatted_deps[#formatted_deps + 1] = "#ccf" + formatted_deps[#formatted_deps + 1] = fgettext("Already installed") + elseif dep.package then + formatted_deps[#formatted_deps + 1] = "#cfc" + formatted_deps[#formatted_deps + 1] = fgettext("$1 by $2", dep.package.title, dep.package.author) + deps_to_install = deps_to_install + 1 + else + formatted_deps[#formatted_deps + 1] = "#f00" + formatted_deps[#formatted_deps + 1] = fgettext("Not found") + deps_not_found = deps_not_found + 1 + end + end + + local message_bg = "#3333" + local message + if will_install_deps then + message = fgettext("$1 and $2 dependencies will be installed.", package.title, deps_to_install) + else + message = fgettext("$1 will be installed, and $2 dependencies will be skipped.", package.title, deps_to_install) + end + if deps_not_found > 0 then + message = fgettext("$1 required dependencies could not be found.", deps_not_found) .. + " " .. fgettext("Please check that the base game is correct.", deps_not_found) .. + "\n" .. message + message_bg = mt_color_orange + end + + local formspec = { + "formspec_version[3]", + "size[7,7.85]", + "style[title;border=false]", + "box[0,0;7,0.5;#3333]", + "button[0,0;7,0.5;title;", fgettext("Install $1", package.title) , "]", + + "container[0.375,0.70]", + + "label[0,0.25;", fgettext("Base Game:"), "]", + "dropdown[2,0;4.25,0.5;gameid;", table.concat(games, ","), ";", selected_game_idx, "]", + + "label[0,0.8;", fgettext("Dependencies:"), "]", + + "tablecolumns[color;text;color;text]", + "table[0,1.1;6.25,3;packages;", table.concat(formatted_deps, ","), "]", + + "container_end[]", + + "checkbox[0.375,5.1;will_install_deps;", + fgettext("Install missing dependencies"), ";", + will_install_deps and "true" or "false", "]", + + "box[0,5.4;7,1.2;", message_bg, "]", + "textarea[0.375,5.5;6.25,1;;;", message, "]", + + "container[1.375,6.85]", + "button[0,0;2,0.8;install_all;", fgettext("Install"), "]", + "button[2.25,0;2,0.8;cancel;", fgettext("Cancel"), "]", + "container_end[]", + } + + return table.concat(formspec, "") +end + +function install_dialog.handle_submit(this, fields) + if fields.cancel then + this:delete() + return true + end + + if fields.will_install_deps ~= nil then + install_dialog.will_install_deps = minetest.is_yes(fields.will_install_deps) + return true + end + + if fields.install_all then + queue_download(install_dialog.package) + + if install_dialog.will_install_deps then + for _, dep in pairs(install_dialog.dependencies) do + if not dep.is_optional and not dep.installed and dep.package then + queue_download(dep.package) + end + end + end + + this:delete() + return true + end + + if fields.gameid then + for _, game in pairs(pkgmgr.games) do + if game.name == fields.gameid then + core.settings:set("menu_last_game", game.id) + break + end + end + return true + end + + return false +end + +function install_dialog.create(package, raw_deps) + install_dialog.dependencies = nil + install_dialog.package = package + install_dialog.raw_deps = raw_deps + install_dialog.will_install_deps = true + return dialog_create("package_view", + install_dialog.get_formspec, + install_dialog.handle_submit, + nil) +end + local function get_file_extension(path) local parts = path:split(".") return parts[#parts] @@ -570,15 +854,24 @@ function store.handle_submit(this, fields) assert(package) if fields["install_" .. i] then - queue_download(package) + local deps = get_raw_dependencies(package) + if deps and has_hard_deps(deps) then + local dlg = install_dialog.create(package, deps) + dlg:set_parent(this) + this:hide() + dlg:show() + else + queue_download(package) + end + return true end if fields["uninstall_" .. i] then - local dlg_delmod = create_delete_content_dlg(package) - dlg_delmod:set_parent(this) + local dlg = create_delete_content_dlg(package) + dlg:set_parent(this) this:hide() - dlg_delmod:show() + dlg:show() return true end diff --git a/builtin/mainmenu/dlg_create_world.lua b/builtin/mainmenu/dlg_create_world.lua index 7566d2409..5931496c1 100644 --- a/builtin/mainmenu/dlg_create_world.lua +++ b/builtin/mainmenu/dlg_create_world.lua @@ -98,7 +98,7 @@ local function create_world_formspec(dialogdata) -- Error out when no games found if #pkgmgr.games == 0 then return "size[12.25,3,true]" .. - "box[0,0;12,2;#ff8800]" .. + "box[0,0;12,2;" .. mt_color_orange .. "]" .. "textarea[0.3,0;11.7,2;;;".. fgettext("You have no games installed.") .. "\n" .. fgettext("Download one from minetest.net") .. "]" .. diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 96d02d06c..2fc0ae64c 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -19,6 +19,7 @@ mt_color_grey = "#AAAAAA" mt_color_blue = "#6389FF" mt_color_green = "#72FF63" mt_color_dark_green = "#25C191" +mt_color_orange = "#FF8800" local menupath = core.get_mainmenu_path() local basepath = core.get_builtin_path() diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 7060a0b6e..7e23b5641 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -2205,4 +2205,5 @@ contentdb_url (ContentDB URL) string https://content.minetest.net contentdb_flag_blacklist (ContentDB Flag Blacklist) string nonfree, desktop_default # Maximum number of concurrent downloads. Downloads exceeding this limit will be queued. +# This should be lower than curl_parallel_limit. contentdb_max_concurrent_downloads (ContentDB Max Concurrent Downloads) int 3 -- cgit v1.2.3 From 8f72d4b2940f0bd5486e38bd58127d14a1762be8 Mon Sep 17 00:00:00 2001 From: Lars Mueller Date: Thu, 24 Dec 2020 14:48:05 +0100 Subject: Fix minetest.is_nan --- builtin/common/misc_helpers.lua | 4 ++++ src/script/lua_api/l_util.cpp | 11 ----------- src/script/lua_api/l_util.h | 3 --- 3 files changed, 4 insertions(+), 14 deletions(-) (limited to 'builtin') diff --git a/builtin/common/misc_helpers.lua b/builtin/common/misc_helpers.lua index e29a9f422..0f3897f47 100644 --- a/builtin/common/misc_helpers.lua +++ b/builtin/common/misc_helpers.lua @@ -697,3 +697,7 @@ function core.privs_to_string(privs, delim) end return table.concat(list, delim) end + +function core.is_nan(number) + return number ~= number +end diff --git a/src/script/lua_api/l_util.cpp b/src/script/lua_api/l_util.cpp index cd63e20c2..6490eb578 100644 --- a/src/script/lua_api/l_util.cpp +++ b/src/script/lua_api/l_util.cpp @@ -239,15 +239,6 @@ int ModApiUtil::l_is_yes(lua_State *L) return 1; } -// is_nan(arg) -int ModApiUtil::l_is_nan(lua_State *L) -{ - NO_MAP_LOCK_REQUIRED; - - lua_pushboolean(L, isNaN(L, 1)); - return 1; -} - // get_builtin_path() int ModApiUtil::l_get_builtin_path(lua_State *L) { @@ -493,7 +484,6 @@ void ModApiUtil::Initialize(lua_State *L, int top) API_FCT(get_password_hash); API_FCT(is_yes); - API_FCT(is_nan); API_FCT(get_builtin_path); @@ -526,7 +516,6 @@ void ModApiUtil::InitializeClient(lua_State *L, int top) API_FCT(write_json); API_FCT(is_yes); - API_FCT(is_nan); API_FCT(compress); API_FCT(decompress); diff --git a/src/script/lua_api/l_util.h b/src/script/lua_api/l_util.h index 9ff91bb53..b6c1b58af 100644 --- a/src/script/lua_api/l_util.h +++ b/src/script/lua_api/l_util.h @@ -65,9 +65,6 @@ private: // is_yes(arg) static int l_is_yes(lua_State *L); - // is_nan(arg) - static int l_is_nan(lua_State *L); - // get_builtin_path() static int l_get_builtin_path(lua_State *L); -- cgit v1.2.3 From 55dba1bc6d90c90ddd77d60f4760e34e28a6382f Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Mon, 28 Dec 2020 12:56:58 +0000 Subject: Display Minetest header when menu_last_game value isn't available anymore (#10751) --- builtin/mainmenu/init.lua | 10 ++++++++++ builtin/mainmenu/tab_local.lua | 1 + 2 files changed, 11 insertions(+) (limited to 'builtin') diff --git a/builtin/mainmenu/init.lua b/builtin/mainmenu/init.lua index 2fc0ae64c..656d1d149 100644 --- a/builtin/mainmenu/init.lua +++ b/builtin/mainmenu/init.lua @@ -106,6 +106,16 @@ local function init_globals() if last_tab and tv_main.current_tab ~= last_tab then tv_main:set_tab(last_tab) end + + -- In case the folder of the last selected game has been deleted, + -- display "Minetest" as a header + if tv_main.current_tab == "local" then + local game = pkgmgr.find_by_gameid(core.settings:get("menu_last_game")) + if game == nil then + mm_texture.reset() + end + end + ui.set_default("maintab") tv_main:show() diff --git a/builtin/mainmenu/tab_local.lua b/builtin/mainmenu/tab_local.lua index 1aee246fc..2eb4752bc 100644 --- a/builtin/mainmenu/tab_local.lua +++ b/builtin/mainmenu/tab_local.lua @@ -18,6 +18,7 @@ local enable_gamebar = PLATFORM ~= "Android" local current_game, singleplayer_refresh_gamebar + if enable_gamebar then function current_game() local last_game_id = core.settings:get("menu_last_game") -- cgit v1.2.3 From 92aac69b36d37ace8d2e06721cfa5e488427dcdf Mon Sep 17 00:00:00 2001 From: Zughy <63455151+Zughy@users.noreply.github.com> Date: Sat, 2 Jan 2021 15:13:02 +0100 Subject: "Browse online content" formspec improvement (#10756) --- LICENSE.txt | 11 ++++++ builtin/mainmenu/dlg_contentstore.lua | 68 +++++++++++++++++---------------- textures/base/pack/cdb_add.png | Bin 0 -> 147 bytes textures/base/pack/cdb_clear.png | Bin 0 -> 182 bytes textures/base/pack/cdb_downloading.png | Bin 0 -> 201 bytes textures/base/pack/cdb_queued.png | Bin 0 -> 210 bytes textures/base/pack/cdb_update.png | Bin 0 -> 173 bytes textures/base/pack/cdb_viewonline.png | Bin 0 -> 191 bytes 8 files changed, 47 insertions(+), 32 deletions(-) create mode 100644 textures/base/pack/cdb_add.png create mode 100644 textures/base/pack/cdb_clear.png create mode 100644 textures/base/pack/cdb_downloading.png create mode 100644 textures/base/pack/cdb_queued.png create mode 100644 textures/base/pack/cdb_update.png create mode 100644 textures/base/pack/cdb_viewonline.png (limited to 'builtin') diff --git a/LICENSE.txt b/LICENSE.txt index 9fbd23723..9b8ee851a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -11,6 +11,9 @@ http://creativecommons.org/licenses/by-sa/3.0/ textures/base/pack/refresh.png is under the Apache 2 license https://www.apache.org/licenses/LICENSE-2.0.html +Textures by Zughy are under CC BY-SA 4.0 +https://creativecommons.org/licenses/by-sa/4.0/ + Authors of media files ----------------------- Everything not listed in here: @@ -47,6 +50,14 @@ srifqi textures/base/pack/joystick_off.png textures/base/pack/minimap_btn.png +Zughy: + textures/base/pack/cdb_add.png + textures/base/pack/cdb_clear.png + textures/base/pack/cdb_downloading.png + textures/base/pack/cdb_queued.png + textures/base/pack/cdb_update.png + textures/base/pack/cdb_viewonline.png + License of Minetest source code ------------------------------- diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 548bae67e..7f6b4b7e4 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -631,7 +631,7 @@ function store.get_formspec(dlgdata) "size[15.75,9.5]", "position[0.5,0.55]", - "style[status;border=false]", + "style[status,downloading,queued;border=false]", "container[0.375,0.375]", "field[0,0;7.225,0.8;search_string;;", core.formspec_escape(search_string), "]", @@ -658,7 +658,7 @@ function store.get_formspec(dlgdata) } if number_downloading > 0 then - formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;status;" + formspec[#formspec + 1] = "button[12.75,0.375;2.625,0.8;downloading;" if #download_queue > 0 then formspec[#formspec + 1] = fgettext("$1 downloading,\n$2 queued", number_downloading, #download_queue) else @@ -702,11 +702,17 @@ function store.get_formspec(dlgdata) } end + -- download/queued tooltips always have the same message + local tooltip_colors = ";#dff6f5;#302c2e]" + formspec[#formspec + 1] = "tooltip[downloading;" .. fgettext("Downloading...") .. tooltip_colors + formspec[#formspec + 1] = "tooltip[queued;" .. fgettext("Queued") .. tooltip_colors + local start_idx = (cur_page - 1) * num_per_page + 1 for i=start_idx, math.min(#store.packages, start_idx+num_per_page-1) do local package = store.packages[i] + local container_y = (i - start_idx) * 1.375 + (2*0.375 + 0.8) formspec[#formspec + 1] = "container[0.375," - formspec[#formspec + 1] = (i - start_idx) * 1.375 + (2*0.375 + 0.8) + formspec[#formspec + 1] = container_y formspec[#formspec + 1] = "]" -- image @@ -722,52 +728,50 @@ function store.get_formspec(dlgdata) formspec[#formspec + 1] = "]" -- buttons - local description_width = W - 0.375*5 - 1 - 2*1.5 + local left_base = "image_button[-1.55,0;0.7,0.7;" .. core.formspec_escape(defaulttexturedir) formspec[#formspec + 1] = "container[" formspec[#formspec + 1] = W - 0.375*2 formspec[#formspec + 1] = ",0.1]" if package.downloading then - formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" - formspec[#formspec + 1] = fgettext("Downloading...") - formspec[#formspec + 1] = "]" + formspec[#formspec + 1] = "animated_image[-1.7,-0.15;1,1;downloading;" + formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir) + formspec[#formspec + 1] = "cdb_downloading.png;3;400;]" elseif package.queued then - formspec[#formspec + 1] = "button[-3.5,0;2,0.8;status;" - formspec[#formspec + 1] = fgettext("Queued") - formspec[#formspec + 1] = "]" + formspec[#formspec + 1] = left_base + formspec[#formspec + 1] = core.formspec_escape(defaulttexturedir) + formspec[#formspec + 1] = "cdb_queued.png;queued]" elseif not package.path then - formspec[#formspec + 1] = "button[-3,0;1.5,0.8;install_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Install") - formspec[#formspec + 1] = "]" + local elem_name = "install_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#71aa34]" + formspec[#formspec + 1] = left_base .. "cdb_add.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Install") .. tooltip_colors else if package.installed_release < package.release then - description_width = description_width - 1.5 -- The install_ action also handles updating - formspec[#formspec + 1] = "button[-4.5,0;1.5,0.8;install_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Update") - formspec[#formspec + 1] = "]" - end + local elem_name = "install_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#28ccdf]" + formspec[#formspec + 1] = left_base .. "cdb_update.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Update") .. tooltip_colors + else - formspec[#formspec + 1] = "button[-3,0;1.5,0.8;uninstall_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("Uninstall") - formspec[#formspec + 1] = "]" + local elem_name = "uninstall_" .. i .. ";" + formspec[#formspec + 1] = "style[" .. elem_name .. "bgcolor=#a93b3b]" + formspec[#formspec + 1] = left_base .. "cdb_clear.png;" .. elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. elem_name .. fgettext("Uninstall") .. tooltip_colors + end end - formspec[#formspec + 1] = "button[-1.5,0;1.5,0.8;view_" - formspec[#formspec + 1] = tostring(i) - formspec[#formspec + 1] = ";" - formspec[#formspec + 1] = fgettext("View") - formspec[#formspec + 1] = "]" + local web_elem_name = "view_" .. i .. ";" + formspec[#formspec + 1] = "image_button[-0.7,0;0.7,0.7;" .. + core.formspec_escape(defaulttexturedir) .. "cdb_viewonline.png;" .. web_elem_name .. "]" + formspec[#formspec + 1] = "tooltip[" .. web_elem_name .. + fgettext("View more information in a web browser") .. tooltip_colors formspec[#formspec + 1] = "container_end[]" -- description + local description_width = W - 0.375*5 - 0.85 - 2*0.7 formspec[#formspec + 1] = "textarea[1.855,0.3;" formspec[#formspec + 1] = tostring(description_width) formspec[#formspec + 1] = ",0.8;;;" diff --git a/textures/base/pack/cdb_add.png b/textures/base/pack/cdb_add.png new file mode 100644 index 000000000..3e3d067e3 Binary files /dev/null and b/textures/base/pack/cdb_add.png differ diff --git a/textures/base/pack/cdb_clear.png b/textures/base/pack/cdb_clear.png new file mode 100644 index 000000000..4490d41cb Binary files /dev/null and b/textures/base/pack/cdb_clear.png differ diff --git a/textures/base/pack/cdb_downloading.png b/textures/base/pack/cdb_downloading.png new file mode 100644 index 000000000..8cba383cc Binary files /dev/null and b/textures/base/pack/cdb_downloading.png differ diff --git a/textures/base/pack/cdb_queued.png b/textures/base/pack/cdb_queued.png new file mode 100644 index 000000000..6972f7fb8 Binary files /dev/null and b/textures/base/pack/cdb_queued.png differ diff --git a/textures/base/pack/cdb_update.png b/textures/base/pack/cdb_update.png new file mode 100644 index 000000000..262e42d3b Binary files /dev/null and b/textures/base/pack/cdb_update.png differ diff --git a/textures/base/pack/cdb_viewonline.png b/textures/base/pack/cdb_viewonline.png new file mode 100644 index 000000000..ae2a146b8 Binary files /dev/null and b/textures/base/pack/cdb_viewonline.png differ -- cgit v1.2.3 From dd5a732fa90550066bb96305b64b6648903cc822 Mon Sep 17 00:00:00 2001 From: hecks <42101236+hecktest@users.noreply.github.com> Date: Sat, 2 Jan 2021 15:14:29 +0100 Subject: Add on_deactivate callback for luaentities (#10723) --- builtin/profiler/instrumentation.lua | 1 + doc/lua_api.txt | 2 ++ games/devtest/mods/testentities/callbacks.lua | 3 ++ src/script/cpp_api/s_entity.cpp | 26 ++++++++++++++ src/script/cpp_api/s_entity.h | 1 + src/script/lua_api/l_object.cpp | 2 +- src/server/luaentity_sao.cpp | 13 +++++-- src/server/luaentity_sao.h | 5 +++ src/server/player_sao.cpp | 2 +- src/server/serveractiveobject.cpp | 16 +++++++++ src/server/serveractiveobject.h | 50 +++++++++++++++++---------- src/serverenvironment.cpp | 12 ++++--- 12 files changed, 106 insertions(+), 27 deletions(-) (limited to 'builtin') diff --git a/builtin/profiler/instrumentation.lua b/builtin/profiler/instrumentation.lua index 237f048fb..6b951a2c2 100644 --- a/builtin/profiler/instrumentation.lua +++ b/builtin/profiler/instrumentation.lua @@ -160,6 +160,7 @@ local function init() -- Simple iteration would ignore lookup via __index. local entity_instrumentation = { "on_activate", + "on_deactivate", "on_step", "on_punch", "on_rightclick", diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8bf6ade69..47c2776e6 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4207,6 +4207,8 @@ Callbacks: * Called when the object is instantiated. * `dtime_s` is the time passed since the object was unloaded, which can be used for updating the entity state. +* `on_deactivate(self) + * Called when the object is about to get removed or unloaded. * `on_step(self, dtime)` * Called on every server tick, after movement and collision processing. `dtime` is usually 0.1 seconds, as per the `dedicated_server_step` setting diff --git a/games/devtest/mods/testentities/callbacks.lua b/games/devtest/mods/testentities/callbacks.lua index 711079f87..320690b39 100644 --- a/games/devtest/mods/testentities/callbacks.lua +++ b/games/devtest/mods/testentities/callbacks.lua @@ -31,6 +31,9 @@ minetest.register_entity("testentities:callback", { on_activate = function(self, staticdata, dtime_s) message("Callback entity: on_activate! pos="..spos(self).."; dtime_s="..dtime_s) end, + on_deactivate = function(self) + message("Callback entity: on_deactivate! pos="..spos(self)) + end, on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir, damage) local name = get_object_name(puncher) message( diff --git a/src/script/cpp_api/s_entity.cpp b/src/script/cpp_api/s_entity.cpp index ea9320051..746f7013e 100644 --- a/src/script/cpp_api/s_entity.cpp +++ b/src/script/cpp_api/s_entity.cpp @@ -103,6 +103,32 @@ void ScriptApiEntity::luaentity_Activate(u16 id, lua_pop(L, 2); // Pop object and error handler } +void ScriptApiEntity::luaentity_Deactivate(u16 id) +{ + SCRIPTAPI_PRECHECKHEADER + + verbosestream << "scriptapi_luaentity_deactivate: id=" << id << std::endl; + + int error_handler = PUSH_ERROR_HANDLER(L); + + // Get the entity + luaentity_get(L, id); + int object = lua_gettop(L); + + // Get on_deactivate + lua_getfield(L, -1, "on_deactivate"); + if (!lua_isnil(L, -1)) { + luaL_checktype(L, -1, LUA_TFUNCTION); + lua_pushvalue(L, object); + + setOriginFromTable(object); + PCALL_RES(lua_pcall(L, 1, 0, error_handler)); + } else { + lua_pop(L, 1); + } + lua_pop(L, 2); // Pop object and error handler +} + void ScriptApiEntity::luaentity_Remove(u16 id) { SCRIPTAPI_PRECHECKHEADER diff --git a/src/script/cpp_api/s_entity.h b/src/script/cpp_api/s_entity.h index b5f7a6586..b52f6e447 100644 --- a/src/script/cpp_api/s_entity.h +++ b/src/script/cpp_api/s_entity.h @@ -33,6 +33,7 @@ public: bool luaentity_Add(u16 id, const char *name); void luaentity_Activate(u16 id, const std::string &staticdata, u32 dtime_s); + void luaentity_Deactivate(u16 id); void luaentity_Remove(u16 id); std::string luaentity_GetStaticdata(u16 id); void luaentity_GetProperties(u16 id, diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 4d7a1bc41..f52e4892e 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -110,7 +110,7 @@ int ObjectRef::l_remove(lua_State *L) sao->clearParentAttachment(); verbosestream << "ObjectRef::l_remove(): id=" << sao->getId() << std::endl; - sao->m_pending_removal = true; + sao->markForRemoval(); return 0; } diff --git a/src/server/luaentity_sao.cpp b/src/server/luaentity_sao.cpp index b39797531..c7277491a 100644 --- a/src/server/luaentity_sao.cpp +++ b/src/server/luaentity_sao.cpp @@ -112,6 +112,15 @@ void LuaEntitySAO::addedToEnvironment(u32 dtime_s) } } +void LuaEntitySAO::dispatchScriptDeactivate() +{ + // Ensure that this is in fact a registered entity, + // and that it isn't already gone. + // The latter also prevents this from ever being called twice. + if (m_registered && !isGone()) + m_env->getScriptIface()->luaentity_Deactivate(m_id); +} + void LuaEntitySAO::step(float dtime, bool send_recommended) { if(!m_properties_sent) @@ -302,7 +311,7 @@ u16 LuaEntitySAO::punch(v3f dir, { if (!m_registered) { // Delete unknown LuaEntities when punched - m_pending_removal = true; + markForRemoval(); return 0; } @@ -335,7 +344,7 @@ u16 LuaEntitySAO::punch(v3f dir, clearParentAttachment(); clearChildAttachments(); m_env->getScriptIface()->luaentity_on_death(m_id, puncher); - m_pending_removal = true; + markForRemoval(); } actionstream << puncher->getDescription() << " (id=" << puncher->getId() << diff --git a/src/server/luaentity_sao.h b/src/server/luaentity_sao.h index e060aa06d..6883ae1b9 100644 --- a/src/server/luaentity_sao.h +++ b/src/server/luaentity_sao.h @@ -71,6 +71,11 @@ public: bool getSelectionBox(aabb3f *toset) const; bool collideWithObjects() const; +protected: + void dispatchScriptDeactivate(); + virtual void onMarkedForDeactivation() { dispatchScriptDeactivate(); } + virtual void onMarkedForRemoval() { dispatchScriptDeactivate(); } + private: std::string getPropertyPacket(); void sendPosition(bool do_interpolate, bool is_movement_end); diff --git a/src/server/player_sao.cpp b/src/server/player_sao.cpp index 62515d1c9..232c6a01d 100644 --- a/src/server/player_sao.cpp +++ b/src/server/player_sao.cpp @@ -531,7 +531,7 @@ bool PlayerSAO::setWieldedItem(const ItemStack &item) void PlayerSAO::disconnected() { m_peer_id = PEER_ID_INEXISTENT; - m_pending_removal = true; + markForRemoval(); } void PlayerSAO::unlinkPlayerSessionAndSave() diff --git a/src/server/serveractiveobject.cpp b/src/server/serveractiveobject.cpp index 8cb59b2d6..96b433d1d 100644 --- a/src/server/serveractiveobject.cpp +++ b/src/server/serveractiveobject.cpp @@ -73,3 +73,19 @@ void ServerActiveObject::dumpAOMessagesToQueue(std::queue & m_messages_out.pop(); } } + +void ServerActiveObject::markForRemoval() +{ + if (!m_pending_removal) { + onMarkedForRemoval(); + m_pending_removal = true; + } +} + +void ServerActiveObject::markForDeactivation() +{ + if (!m_pending_deactivation) { + onMarkedForDeactivation(); + m_pending_deactivation = true; + } +} diff --git a/src/server/serveractiveobject.h b/src/server/serveractiveobject.h index 2764d159e..25653a1ad 100644 --- a/src/server/serveractiveobject.h +++ b/src/server/serveractiveobject.h @@ -70,6 +70,10 @@ public: virtual bool environmentDeletes() const { return true; } + // Safely mark the object for removal or deactivation + void markForRemoval(); + void markForDeactivation(); + // Create a certain type of ServerActiveObject static ServerActiveObject* create(ActiveObjectType type, ServerEnvironment *env, u16 id, v3f pos, @@ -213,25 +217,6 @@ public: */ u16 m_known_by_count = 0; - /* - - Whether this object is to be removed when nobody knows about - it anymore. - - Removal is delayed to preserve the id for the time during which - it could be confused to some other object by some client. - - This is usually set to true by the step() method when the object wants - to be deleted but can be set by anything else too. - */ - bool m_pending_removal = false; - - /* - Same purpose as m_pending_removal but for deactivation. - deactvation = save static data in block, remove active object - - If this is set alongside with m_pending_removal, removal takes - priority. - */ - bool m_pending_deactivation = false; - /* A getter that unifies the above to answer the question: "Can the environment still interact with this object?" @@ -239,6 +224,9 @@ public: inline bool isGone() const { return m_pending_removal || m_pending_deactivation; } + inline bool isPendingRemoval() const + { return m_pending_removal; } + /* Whether the object's static data has been stored to a block */ @@ -250,6 +238,9 @@ public: v3s16 m_static_block = v3s16(1337,1337,1337); protected: + virtual void onMarkedForDeactivation() {} + virtual void onMarkedForRemoval() {} + virtual void onAttach(int parent_id) {} virtual void onDetach(int parent_id) {} @@ -257,6 +248,27 @@ protected: v3f m_base_position; std::unordered_set m_attached_particle_spawners; + /* + Same purpose as m_pending_removal but for deactivation. + deactvation = save static data in block, remove active object + + If this is set alongside with m_pending_removal, removal takes + priority. + Note: Do not assign this directly, use markForDeactivation() instead. + */ + bool m_pending_deactivation = false; + + /* + - Whether this object is to be removed when nobody knows about + it anymore. + - Removal is delayed to preserve the id for the time during which + it could be confused to some other object by some client. + - This is usually set to true by the step() method when the object wants + to be deleted but can be set by anything else too. + Note: Do not assign this directly, use markForRemoval() instead. + */ + bool m_pending_removal = false; + /* Queue of messages to be sent to the client */ diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index d044b003d..56dbb0632 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -1164,7 +1164,7 @@ void ServerEnvironment::clearObjects(ClearObjectsMode mode) // If known by some client, don't delete immediately if (obj->m_known_by_count > 0) { - obj->m_pending_removal = true; + obj->markForRemoval(); return false; } @@ -1792,7 +1792,7 @@ void ServerEnvironment::removeRemovedObjects() /* Delete static data from block if removed */ - if (obj->m_pending_removal) + if (obj->isPendingRemoval()) deleteStaticFromBlock(obj, id, MOD_REASON_REMOVE_OBJECTS_REMOVE, false); // If still known by clients, don't actually remove. On some future @@ -1803,7 +1803,7 @@ void ServerEnvironment::removeRemovedObjects() /* Move static data from active to stored if deactivated */ - if (!obj->m_pending_removal && obj->m_static_exists) { + if (!obj->isPendingRemoval() && obj->m_static_exists) { MapBlock *block = m_map->emergeBlock(obj->m_static_block, false); if (block) { const auto i = block->m_static_objects.m_active.find(id); @@ -1991,6 +1991,7 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) if (!force_delete && obj->m_static_exists && !m_active_blocks.contains(obj->m_static_block) && m_active_blocks.contains(blockpos_o)) { + // Delete from block where object was located deleteStaticFromBlock(obj, id, MOD_REASON_STATIC_DATA_REMOVED, false); @@ -2068,6 +2069,10 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) force_delete = true; } + // Regardless of what happens to the object at this point, deactivate it first. + // This ensures that LuaEntity on_deactivate is always called. + obj->markForDeactivation(); + /* If known by some client, set pending deactivation. Otherwise delete it immediately. @@ -2077,7 +2082,6 @@ void ServerEnvironment::deactivateFarObjects(bool _force_delete) << "object id=" << id << " is known by clients" << "; not deleting yet" << std::endl; - obj->m_pending_deactivation = true; return false; } -- cgit v1.2.3 From edd083601173c1b67a2e5cd88e23122f46b88bbf Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Mon, 4 Jan 2021 15:18:31 +0000 Subject: ContentDB: Add overwrite dialog when content is already installed (#10768) --- builtin/mainmenu/dlg_contentstore.lua | 74 ++++++++++++++++++++++++++++++++--- doc/menu_lua_api.txt | 2 + src/script/lua_api/l_mainmenu.cpp | 11 ++++++ src/script/lua_api/l_mainmenu.h | 2 + 4 files changed, 84 insertions(+), 5 deletions(-) (limited to 'builtin') diff --git a/builtin/mainmenu/dlg_contentstore.lua b/builtin/mainmenu/dlg_contentstore.lua index 7f6b4b7e4..b5f71e753 100644 --- a/builtin/mainmenu/dlg_contentstore.lua +++ b/builtin/mainmenu/dlg_contentstore.lua @@ -437,12 +437,53 @@ function install_dialog.create(package, raw_deps) install_dialog.package = package install_dialog.raw_deps = raw_deps install_dialog.will_install_deps = true - return dialog_create("package_view", + return dialog_create("install_dialog", install_dialog.get_formspec, install_dialog.handle_submit, nil) end + +local confirm_overwrite = {} +function confirm_overwrite.get_formspec() + local package = confirm_overwrite.package + + return "size[11.5,4.5,true]" .. + "label[2,2;" .. + fgettext("\"$1\" already exists. Would you like to overwrite it?", package.name) .. "]".. + "style[install;bgcolor=red]" .. + "button[3.25,3.5;2.5,0.5;install;" .. fgettext("Overwrite") .. "]" .. + "button[5.75,3.5;2.5,0.5;cancel;" .. fgettext("Cancel") .. "]" +end + +function confirm_overwrite.handle_submit(this, fields) + if fields.cancel then + this:delete() + return true + end + + if fields.install then + this:delete() + confirm_overwrite.callback() + return true + end + + return false +end + +function confirm_overwrite.create(package, callback) + assert(type(package) == "table") + assert(type(callback) == "function") + + confirm_overwrite.package = package + confirm_overwrite.callback = callback + return dialog_create("confirm_overwrite", + confirm_overwrite.get_formspec, + confirm_overwrite.handle_submit, + nil) +end + + local function get_file_extension(path) local parts = path:split(".") return parts[#parts] @@ -858,14 +899,37 @@ function store.handle_submit(this, fields) assert(package) if fields["install_" .. i] then - local deps = get_raw_dependencies(package) - if deps and has_hard_deps(deps) then - local dlg = install_dialog.create(package, deps) + local install_parent + if package.type == "mod" then + install_parent = core.get_modpath() + elseif package.type == "game" then + install_parent = core.get_gamepath() + elseif package.type == "txp" then + install_parent = core.get_texturepath() + else + error("Unknown package type: " .. package.type) + end + + + local function on_confirm() + local deps = get_raw_dependencies(package) + if deps and has_hard_deps(deps) then + local dlg = install_dialog.create(package, deps) + dlg:set_parent(this) + this:hide() + dlg:show() + else + queue_download(package) + end + end + + if not package.path and core.is_dir(install_parent .. DIR_DELIM .. package.name) then + local dlg = confirm_overwrite.create(package, on_confirm) dlg:set_parent(this) this:hide() dlg:show() else - queue_download(package) + on_confirm() end return true diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index 8908552d5..1bcf697e9 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -67,6 +67,8 @@ core.copy_dir(source,destination,keep_soure) (possible in async calls) ^ destination folder ^ keep_source DEFAULT true --> if set to false source is deleted after copying ^ returns true/false +core.is_dir(path) (possible in async calls) +^ returns true if path is a valid dir core.extract_zip(zipfile,destination) [unzip within path required] ^ zipfile to extract ^ destination folder to extract to diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 0b0b2de3b..5070ec7d4 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -803,6 +803,15 @@ int ModApiMainMenu::l_copy_dir(lua_State *L) return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_is_dir(lua_State *L) +{ + const char *path = luaL_checkstring(L, 1); + + lua_pushboolean(L, fs::IsDir(path)); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_extract_zip(lua_State *L) { @@ -1139,6 +1148,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); + API_FCT(is_dir); API_FCT(extract_zip); API_FCT(may_modify_path); API_FCT(get_mainmenu_path); @@ -1172,6 +1182,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); + API_FCT(is_dir); //API_FCT(extract_zip); //TODO remove dependency to GuiEngine API_FCT(may_modify_path); API_FCT(download_file); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index faa2bf273..0b02ed892 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -132,6 +132,8 @@ private: static int l_copy_dir(lua_State *L); + static int l_is_dir(lua_State *L); + static int l_extract_zip(lua_State *L); static int l_may_modify_path(lua_State *L); -- cgit v1.2.3