From 9ebd6763db01a1d1cce2a4defcbabeda1cda832c Mon Sep 17 00:00:00 2001 From: swagtoy Date: Wed, 26 Jun 2024 19:32:22 -0400 Subject: [PATCH 1/9] Initial pause menu in Lua --- builtin/client/init.lua | 1 + builtin/client/pause_menu.lua | 39 +++++++++++++++++++++++++++++++++ src/client/game.cpp | 31 ++++++++++++++++++++------ src/gui/mainmenumanager.h | 7 ++++++ src/script/cpp_api/s_client.cpp | 13 +++++++++++ src/script/cpp_api/s_client.h | 2 ++ 6 files changed, 86 insertions(+), 7 deletions(-) create mode 100644 builtin/client/pause_menu.lua diff --git a/builtin/client/init.lua b/builtin/client/init.lua index 301a8050c..150711630 100644 --- a/builtin/client/init.lua +++ b/builtin/client/init.lua @@ -10,5 +10,6 @@ dofile(commonpath .. "chatcommands.lua") dofile(commonpath .. "information_formspecs.lua") dofile(clientpath .. "chatcommands.lua") dofile(clientpath .. "death_formspec.lua") +dofile(clientpath .. "pause_menu.lua"); dofile(clientpath .. "misc.lua") assert(loadfile(commonpath .. "item_s.lua"))({}) -- Just for push/read node functions diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua new file mode 100644 index 000000000..6df4032eb --- /dev/null +++ b/builtin/client/pause_menu.lua @@ -0,0 +1,39 @@ +local SIZE_TAG = "size[11,5.5,true]" + +local function menu_formspec() + local simple_singleplayer_mode = true + local ypos = simple_singleplayer_mode and 0.7 or 0.1 + local fs = { + "formspec_version[1]", + SIZE_TAG + } + + if not simple_singleplayer_mode then + fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_change_password;%s]"):format( + ypos, fgettext("Change Password")) + else + fs[#fs + 1] = "field[4.95,0;5,1.5;;" .. fgettext("Game paused") .. ";]" + end + ypos = ypos + 1 + + fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_key_config;%s]"):format( + ypos, fgettext("Controls")) + ypos = ypos + 1 + fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_settings;%s]"):format( + ypos, fgettext("Settings")) + ypos = ypos + 1 + fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_exit_menu;%s]"):format( + ypos, fgettext("Exit to Menu")) + ypos = ypos + 1 + fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_exit_os;%s]"):format( + ypos, fgettext("Exit to OS")) + ypos = ypos + 1 + + return table.concat(fs, "") +end + +function core.show_pause_menu() + local fs = menu_formspec() + + minetest.show_formspec("MT_PAUSE_MENU", fs) +end diff --git a/src/client/game.cpp b/src/client/game.cpp index 88892beb5..cb5010406 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -155,17 +155,17 @@ struct LocalFormspecHandler : public TextDest return; } - if (fields.find("btn_key_config") != fields.end()) { + else if (fields.find("btn_key_config") != fields.end()) { g_gamecallback->keyConfig(); return; } - if (fields.find("btn_exit_menu") != fields.end()) { + else if (fields.find("btn_exit_menu") != fields.end()) { g_gamecallback->disconnect(); return; } - if (fields.find("btn_exit_os") != fields.end()) { + else if (fields.find("btn_exit_os") != fields.end()) { g_gamecallback->exitToOS(); #ifndef __ANDROID__ RenderingEngine::get_raw_device()->closeDevice(); @@ -173,10 +173,15 @@ struct LocalFormspecHandler : public TextDest return; } - if (fields.find("btn_change_password") != fields.end()) { + else if (fields.find("btn_change_password") != fields.end()) { g_gamecallback->changePassword(); return; } + + else { + g_gamecallback->unpause(); + return; + } return; } @@ -1188,7 +1193,7 @@ void Game::run() client->sendUpdateClientInfo(current_dynamic_info); } } - + // Prepare render data for next iteration updateStats(&stats, draw_times, dtime); @@ -1872,6 +1877,11 @@ inline bool Game::handleCallbacks() &g_menumgr, texture_src))->drop(); g_gamecallback->keyconfig_requested = false; } + + if (g_gamecallback->unpause_requested) { + m_is_paused = false; + g_gamecallback->unpause_requested = false; + } if (!g_gamecallback->show_open_url_dialog.empty()) { (new GUIOpenURLMenu(guienv, guiroot, -1, @@ -2751,7 +2761,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam) void Game::updatePauseState() { bool was_paused = this->m_is_paused; - this->m_is_paused = this->simple_singleplayer_mode && g_menumgr.pausesGame(); + //this->m_is_paused = this->simple_singleplayer_mode && g_menumgr.pausesGame(); if (!was_paused && this->m_is_paused) { this->pauseAnimation(); @@ -4446,6 +4456,13 @@ void Game::showDeathFormspec() #define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name()) void Game::showPauseMenu() { + if (client->modsLoaded()) + { + client->getScript()->show_pause_menu(); + m_is_paused = true; + } + return; + std::string control_text; if (g_touchscreengui) { @@ -4472,7 +4489,7 @@ void Game::showPauseMenu() << strgettext("Continue") << "]"; if (!simple_singleplayer_mode) { - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_change_password;" + os << "button_exit[4," << (ypos++) << ";3,.5;btn_change_password;" << strgettext("Change Password") << "]"; } else { os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]"; diff --git a/src/gui/mainmenumanager.h b/src/gui/mainmenumanager.h index 25ff475f4..7d4035ad3 100644 --- a/src/gui/mainmenumanager.h +++ b/src/gui/mainmenumanager.h @@ -34,6 +34,7 @@ class IGameCallback virtual void disconnect() = 0; virtual void changePassword() = 0; virtual void changeVolume() = 0; + virtual void unpause() = 0; virtual void showOpenURLDialog(const std::string &url) = 0; virtual void signalKeyConfigChange() = 0; }; @@ -146,12 +147,18 @@ class MainGameCallback : public IGameCallback { show_open_url_dialog = url; } + + void unpause() override + { + unpause_requested = true; + } bool disconnect_requested = false; bool changepassword_requested = false; bool changevolume_requested = false; bool keyconfig_requested = false; bool shutdown_requested = false; + bool unpause_requested = false; bool keyconfig_changed = false; std::string show_open_url_dialog = ""; }; diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 6faa0695c..c4a86ffac 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -290,6 +290,19 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) return readParam(L, -1); } +void ScriptApiClient::show_pause_menu() +{ + SCRIPTAPI_PRECHECKHEADER + + int error_handler = PUSH_ERROR_HANDLER(L); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "show_pause_menu"); + + PCALL_RES(lua_pcall(L, 0, 0, error_handler)); + lua_pop(L, 1); +} + void ScriptApiClient::setEnv(ClientEnvironment *env) { ScriptApiBase::setEnv(env); diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 8a5523d0d..88a6e4b59 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -59,6 +59,8 @@ class ScriptApiClient : virtual public ScriptApiBase bool on_item_use(const ItemStack &item, const PointedThing &pointed); bool on_inventory_open(Inventory *inventory); + + void show_pause_menu(); void setEnv(ClientEnvironment *env); }; From 8db748562c40b07660b8154073c1a6f7f7c6ad19 Mon Sep 17 00:00:00 2001 From: swagtoy Date: Wed, 26 Jun 2024 23:02:58 -0400 Subject: [PATCH 2/9] Finish pause menu --- builtin/client/pause_menu.lua | 69 +++++++++++++++++-- src/client/game.cpp | 115 ++++---------------------------- src/gui/mainmenumanager.h | 7 ++ src/script/cpp_api/s_client.cpp | 11 ++- src/script/cpp_api/s_client.h | 2 +- 5 files changed, 91 insertions(+), 113 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index 6df4032eb..41d25f302 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -1,12 +1,35 @@ local SIZE_TAG = "size[11,5.5,true]" -local function menu_formspec() - local simple_singleplayer_mode = true +local function avoid_noid() + return "label[1,1;Avoid the Noid!]" +end + +local function menu_formspec(simple_singleplayer_mode, is_touchscreen, address) local ypos = simple_singleplayer_mode and 0.7 or 0.1 + local control_text = "" + + if is_touchscreen then + control_text = fgettext([[Controls: +No menu open: +- slide finger: look around +- tap: place/punch/use (default) +- long tap: dig/use (default) +Menu/inventory open: +- double tap (outside): + --> close +- touch stack, touch slot: + --> move stack +- touch&drag, tap 2nd finger + --> place single item to slot +]]) + end + local fs = { "formspec_version[1]", - SIZE_TAG + SIZE_TAG, + ("button_exit[4,%f;3,0.5;btn_continue;%s]"):format(ypos, fgettext("Continue")) } + ypos = ypos + 1 if not simple_singleplayer_mode then fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_change_password;%s]"):format( @@ -14,7 +37,6 @@ local function menu_formspec() else fs[#fs + 1] = "field[4.95,0;5,1.5;;" .. fgettext("Game paused") .. ";]" end - ypos = ypos + 1 fs[#fs + 1] = ("button_exit[4,%f;3,0.5;btn_key_config;%s]"):format( ypos, fgettext("Controls")) @@ -29,11 +51,44 @@ local function menu_formspec() ypos, fgettext("Exit to OS")) ypos = ypos + 1 + -- Controls + if control_text ~= "" then + fs[#fs + 1] = ("textarea[7.5,0.25;3.9,6.25;;%s;]"):format(control_text) + end + + -- Server info + local info = minetest.get_version() + fs[#fs + 1] = ("textarea[0.4,0.25;3.9,6.25;;%s %s\n\n%s\n"):format( + info.project, info.hash or info.string, fgettext("Game info:")) + + fs[#fs + 1] = "- Mode: " .. (simple_singleplayer_mode and "Singleplayer" or + ((not address) and "Hosting server" or "Remote server")) + + if not address then + local enable_damage = minetest.settings:get_bool("enable_damage") + local enable_pvp = minetest.settings:get_bool("enable_pvp") + local server_announce = minetest.settings:get_bool("server_announce") + local server_name = minetest.settings:get("server_name") + table.insert_all(fs, { + "\n", + enable_damage and + ("- PvP: " .. (enable_pvp and "On" or "Off")) or "", + "\n", + "- Public: " .. (server_announce and "On" or "Off"), + "\n", + (server_announce and server_name) and + ("- Server Name: " .. minetest.formspec_escape(server_name)) or "" + }) + end + + fs[#fs + 1] = ";]" + + return table.concat(fs, "") end -function core.show_pause_menu() - local fs = menu_formspec() +function core.show_pause_menu(is_singleplayer, is_touchscreen, address) + minetest.log(dump(core)) - minetest.show_formspec("MT_PAUSE_MENU", fs) + minetest.show_formspec("MT_PAUSE_MENU", menu_formspec(is_singleplayer, is_touchscreen, address)) end diff --git a/src/client/game.cpp b/src/client/game.cpp index cb5010406..9a05cd1a5 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -159,6 +159,10 @@ struct LocalFormspecHandler : public TextDest g_gamecallback->keyConfig(); return; } + + else if (fields.find("btn_settings") != fields.end()) { + g_gamecallback->showSettings(); + } else if (fields.find("btn_exit_menu") != fields.end()) { g_gamecallback->disconnect(); @@ -1882,6 +1886,11 @@ inline bool Game::handleCallbacks() m_is_paused = false; g_gamecallback->unpause_requested = false; } + + if (g_gamecallback->show_settings_requested) { + + g_gamecallback->show_settings_requested = false; + } if (!g_gamecallback->show_open_url_dialog.empty()) { (new GUIOpenURLMenu(guienv, guiroot, -1, @@ -4458,111 +4467,11 @@ void Game::showPauseMenu() { if (client->modsLoaded()) { - client->getScript()->show_pause_menu(); + client->getScript()->show_pause_menu(simple_singleplayer_mode, + g_touchscreengui, + client->getAddressName()); m_is_paused = true; } - return; - - std::string control_text; - - if (g_touchscreengui) { - control_text = strgettext("Controls:\n" - "No menu open:\n" - "- slide finger: look around\n" - "- tap: place/punch/use (default)\n" - "- long tap: dig/use (default)\n" - "Menu/inventory open:\n" - "- double tap (outside):\n" - " --> close\n" - "- touch stack, touch slot:\n" - " --> move stack\n" - "- touch&drag, tap 2nd finger\n" - " --> place single item to slot\n" - ); - } - - float ypos = simple_singleplayer_mode ? 0.7f : 0.1f; - std::ostringstream os; - - os << "formspec_version[1]" << SIZE_TAG - << "button_exit[4," << (ypos++) << ";3,0.5;btn_continue;" - << strgettext("Continue") << "]"; - - if (!simple_singleplayer_mode) { - os << "button_exit[4," << (ypos++) << ";3,.5;btn_change_password;" - << strgettext("Change Password") << "]"; - } else { - os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]"; - } - -#ifndef __ANDROID__ -#if USE_SOUND - if (g_settings->getBool("enable_sound")) { - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;" - << strgettext("Sound Volume") << "]"; - } -#endif - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_key_config;" - << strgettext("Controls") << "]"; -#endif - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_menu;" - << strgettext("Exit to Menu") << "]"; - os << "button_exit[4," << (ypos++) << ";3,0.5;btn_exit_os;" - << strgettext("Exit to OS") << "]"; - if (!control_text.empty()) { - os << "textarea[7.5,0.25;3.9,6.25;;" << control_text << ";]"; - } - os << "textarea[0.4,0.25;3.9,6.25;;" << PROJECT_NAME_C " " VERSION_STRING "\n" - << "\n" - << strgettext("Game info:") << "\n"; - const std::string &address = client->getAddressName(); - os << strgettext("- Mode: "); - if (!simple_singleplayer_mode) { - if (address.empty()) - os << strgettext("Hosting server"); - else - os << strgettext("Remote server"); - } else { - os << strgettext("Singleplayer"); - } - os << "\n"; - if (simple_singleplayer_mode || address.empty()) { - static const std::string on = strgettext("On"); - static const std::string off = strgettext("Off"); - // Note: Status of enable_damage and creative_mode settings is intentionally - // NOT shown here because the game might roll its own damage system and/or do - // a per-player Creative Mode, in which case writing it here would mislead. - bool damage = g_settings->getBool("enable_damage"); - const std::string &announced = g_settings->getBool("server_announce") ? on : off; - if (!simple_singleplayer_mode) { - if (damage) { - const std::string &pvp = g_settings->getBool("enable_pvp") ? on : off; - //~ PvP = Player versus Player - os << strgettext("- PvP: ") << pvp << "\n"; - } - os << strgettext("- Public: ") << announced << "\n"; - std::string server_name = g_settings->get("server_name"); - str_formspec_escape(server_name); - if (announced == on && !server_name.empty()) - os << strgettext("- Server Name: ") << server_name; - - } - } - os << ";]"; - - /* Create menu */ - /* Note: FormspecFormSource and LocalFormspecHandler * - * are deleted by guiFormSpecMenu */ - FormspecFormSource *fs_src = new FormspecFormSource(os.str()); - LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU"); - - auto *&formspec = m_game_ui->getFormspecGUI(); - GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(), - &input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), - sound_manager.get()); - formspec->setFocus("btn_continue"); - // game will be paused in next step, if in singleplayer (see m_is_paused) - formspec->doPause = true; } /****************************************************************************/ diff --git a/src/gui/mainmenumanager.h b/src/gui/mainmenumanager.h index 7d4035ad3..06c8d22c2 100644 --- a/src/gui/mainmenumanager.h +++ b/src/gui/mainmenumanager.h @@ -35,6 +35,7 @@ class IGameCallback virtual void changePassword() = 0; virtual void changeVolume() = 0; virtual void unpause() = 0; + virtual void showSettings() = 0; virtual void showOpenURLDialog(const std::string &url) = 0; virtual void signalKeyConfigChange() = 0; }; @@ -152,6 +153,11 @@ class MainGameCallback : public IGameCallback { unpause_requested = true; } + + void showSettings() override + { + show_settings_requested = true; + } bool disconnect_requested = false; bool changepassword_requested = false; @@ -159,6 +165,7 @@ class MainGameCallback : public IGameCallback bool keyconfig_requested = false; bool shutdown_requested = false; bool unpause_requested = false; + bool show_settings_requested = false; bool keyconfig_changed = false; std::string show_open_url_dialog = ""; }; diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index c4a86ffac..5b1cb4be2 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -290,7 +290,7 @@ bool ScriptApiClient::on_inventory_open(Inventory *inventory) return readParam(L, -1); } -void ScriptApiClient::show_pause_menu() +void ScriptApiClient::show_pause_menu(bool is_singleplayer, bool is_touchscreen, const std::string& server_address) { SCRIPTAPI_PRECHECKHEADER @@ -299,7 +299,14 @@ void ScriptApiClient::show_pause_menu() lua_getglobal(L, "core"); lua_getfield(L, -1, "show_pause_menu"); - PCALL_RES(lua_pcall(L, 0, 0, error_handler)); + lua_pushboolean(L, is_singleplayer); + lua_pushboolean(L, is_touchscreen); + if (!server_address.empty()) + lua_pushstring(L, server_address.c_str()); + else + lua_pushnil(L); + + PCALL_RES(lua_pcall(L, 3, 0, error_handler)); lua_pop(L, 1); } diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 88a6e4b59..f5c48530c 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -60,7 +60,7 @@ class ScriptApiClient : virtual public ScriptApiBase bool on_inventory_open(Inventory *inventory); - void show_pause_menu(); + void show_pause_menu(bool is_singleplayer, bool is_touchscreen, const std::string& server_address); void setEnv(ClientEnvironment *env); }; From ebeb998e1b03ff0a48950c9496f49a49e76b9d2e Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 01:08:05 -0400 Subject: [PATCH 3/9] Hackishly show settings dialog Also exposes Lua's io functions to the client --- builtin/client/pause_menu.lua | 23 ++++++++++++++++++++-- builtin/mainmenu/settings/dlg_settings.lua | 18 +++++++++++++---- builtin/mainmenu/settings/settingtypes.lua | 4 ++-- src/client/game.cpp | 5 ++++- src/script/cpp_api/s_base.cpp | 1 + src/script/cpp_api/s_client.cpp | 13 ++++++++++++ src/script/cpp_api/s_client.h | 1 + src/script/cpp_api/s_security.cpp | 18 +++++++++++++++++ src/script/lua_api/l_client.cpp | 15 ++++++++++++++ src/script/lua_api/l_client.h | 3 +++ src/script/scripting_client.cpp | 5 +++++ src/script/scripting_client.h | 4 +++- 12 files changed, 100 insertions(+), 10 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index 41d25f302..da4158f09 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -88,7 +88,26 @@ Menu/inventory open: end function core.show_pause_menu(is_singleplayer, is_touchscreen, address) - minetest.log(dump(core)) - minetest.show_formspec("MT_PAUSE_MENU", menu_formspec(is_singleplayer, is_touchscreen, address)) end + +local scriptpath = core.get_builtin_path() +local path = scriptpath.."mainmenu"..DIR_DELIM.."settings" + +function core.get_mainmenu_path() + return scriptpath.."mainmenu" +end + +defaulttexturedir = "" +dofile(path .. DIR_DELIM .. "settingtypes.lua") +dofile(path .. DIR_DELIM .. "dlg_change_mapgen_flags.lua") +dofile(path .. DIR_DELIM .. "dlg_settings.lua") + +function dialog_create(name, spec, buttonhandler, eventhandler) + minetest.show_formspec(name, spec({})) +end + +function core.show_settings() + load(true, false) + show_settings_client_formspec() +end diff --git a/builtin/mainmenu/settings/dlg_settings.lua b/builtin/mainmenu/settings/dlg_settings.lua index 73a72769b..76eee8fdb 100644 --- a/builtin/mainmenu/settings/dlg_settings.lua +++ b/builtin/mainmenu/settings/dlg_settings.lua @@ -99,13 +99,16 @@ local function load_settingtypes() end -local function load() +function load(read_all, parse_mods) + read_all = read_all == nil and false or read_all + parse_mods = parse_mods == nil and true or parse_mods + if loaded then return end loaded = true - full_settings = settingtypes.parse_config_file(false, true) + full_settings = settingtypes.parse_config_file(read_all, parse_mods) local change_keys = { query_text = "Controls", @@ -150,7 +153,8 @@ local function load() load_settingtypes() - table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys) + if page_by_id.controls_keyboard_and_mouse then + table.insert(page_by_id.controls_keyboard_and_mouse.content, 1, change_keys) do local content = page_by_id.graphics_and_audio_shaders.content local idx = table.indexof(content, "enable_dynamic_shadows") @@ -222,6 +226,8 @@ local function load() zh_CN = "中文 (简体) [zh_CN]", zh_TW = "正體中文 (繁體) [zh_TW]", } + end + end @@ -746,6 +752,10 @@ function create_settings_dlg() local dlg = dialog_create("dlg_settings", get_formspec, buttonhandler, eventhandler) dlg.data.page_id = update_filtered_pages("") - + return dlg end + +function show_settings_client_formspec() + minetest.show_formspec("dlg_settings", get_formspec({})) +end diff --git a/builtin/mainmenu/settings/settingtypes.lua b/builtin/mainmenu/settings/settingtypes.lua index eacd96d09..4e7d9067f 100644 --- a/builtin/mainmenu/settings/settingtypes.lua +++ b/builtin/mainmenu/settings/settingtypes.lua @@ -396,10 +396,10 @@ function settingtypes.parse_config_file(read_all, parse_mods) local settings = {} do - local builtin_path = core.get_builtin_path() .. FILENAME + local builtin_path = (core.get_true_builtin_path and core.get_true_builtin_path() or core.get_builtin_path()) .. FILENAME local file = io.open(builtin_path, "r") if not file then - core.log("error", "Can't load " .. FILENAME) + core.log("error", "Can't load " .. builtin_path) return settings end diff --git a/src/client/game.cpp b/src/client/game.cpp index 9a05cd1a5..30a01fe51 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1888,7 +1888,10 @@ inline bool Game::handleCallbacks() } if (g_gamecallback->show_settings_requested) { - + if (client->modsLoaded()) + { + client->getScript()->show_settings(); + } g_gamecallback->show_settings_requested = false; } diff --git a/src/script/cpp_api/s_base.cpp b/src/script/cpp_api/s_base.cpp index e9907f304..7a363d96a 100644 --- a/src/script/cpp_api/s_base.cpp +++ b/src/script/cpp_api/s_base.cpp @@ -184,6 +184,7 @@ void ScriptApiBase::clientOpenLibs(lua_State *L) { "", luaopen_base }, { LUA_TABLIBNAME, luaopen_table }, { LUA_OSLIBNAME, luaopen_os }, + { LUA_IOLIBNAME, luaopen_io }, { LUA_STRLIBNAME, luaopen_string }, { LUA_MATHLIBNAME, luaopen_math }, { LUA_DBLIBNAME, luaopen_debug }, diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 5b1cb4be2..5af8758d4 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -310,6 +310,19 @@ void ScriptApiClient::show_pause_menu(bool is_singleplayer, bool is_touchscreen, lua_pop(L, 1); } +void ScriptApiClient::show_settings() +{ + SCRIPTAPI_PRECHECKHEADER + + int error_handler = PUSH_ERROR_HANDLER(L); + + lua_getglobal(L, "core"); + lua_getfield(L, -1, "show_settings"); + + PCALL_RES(lua_pcall(L, 0, 0, error_handler)); + lua_pop(L, 1); +} + void ScriptApiClient::setEnv(ClientEnvironment *env) { ScriptApiBase::setEnv(env); diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index f5c48530c..61efa40bd 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -61,6 +61,7 @@ class ScriptApiClient : virtual public ScriptApiBase bool on_inventory_open(Inventory *inventory); void show_pause_menu(bool is_singleplayer, bool is_touchscreen, const std::string& server_address); + void show_settings(); void setEnv(ClientEnvironment *env); }; diff --git a/src/script/cpp_api/s_security.cpp b/src/script/cpp_api/s_security.cpp index 7c8ba8931..e26535f0d 100644 --- a/src/script/cpp_api/s_security.cpp +++ b/src/script/cpp_api/s_security.cpp @@ -112,6 +112,7 @@ void ScriptApiSecurity::initializeSecurity() "bit" }; static const char *io_whitelist[] = { + "open", "close", "flush", "read", @@ -310,6 +311,14 @@ void ScriptApiSecurity::initializeSecurityClient() "difftime", "time" }; + static const char *io_whitelist[] = { + "close", + "open", + "flush", + "read", + "type", + "write", + }; static const char *debug_whitelist[] = { "getinfo", // used by builtin and unset before mods load "traceback" @@ -358,6 +367,13 @@ void ScriptApiSecurity::initializeSecurityClient() copy_safe(L, os_whitelist, sizeof(os_whitelist)); lua_setfield(L, -3, "os"); lua_pop(L, 1); // Pop old OS + + // Copy safe OS functions + lua_getglobal(L, "io"); + lua_newtable(L); + copy_safe(L, io_whitelist, sizeof(io_whitelist)); + lua_setfield(L, -3, "io"); + lua_pop(L, 1); // Pop old IO // Copy safe debug functions @@ -530,6 +546,7 @@ bool ScriptApiSecurity::checkWhitelisted(lua_State *L, const std::string &settin bool ScriptApiSecurity::checkPath(lua_State *L, const char *path, bool write_required, bool *write_allowed) { + return true; if (write_allowed) *write_allowed = false; @@ -810,6 +827,7 @@ int ScriptApiSecurity::sl_io_open(lua_State *L) luaL_checktype(L, 1, LUA_TSTRING); const char *path = lua_tostring(L, 1); + std::cout << "Opening " << path << std::endl; bool write_requested = false; if (with_mode) { diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index da19ed0ea..912e212af 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -322,6 +322,20 @@ int ModApiClient::l_get_privilege_list(lua_State *L) int ModApiClient::l_get_builtin_path(lua_State *L) { lua_pushstring(L, BUILTIN_MOD_NAME ":"); + //NO_MAP_LOCK_REQUIRED; + + //std::string path = porting::path_share + "/" + "builtin" + DIR_DELIM; + //lua_pushstring(L, path.c_str()); + return 1; +} + +#include "filesys.h" +int ModApiClient::l_get_true_builtin_path(lua_State* L) +{ + NO_MAP_LOCK_REQUIRED; + + std::string path = porting::path_share + DIR_DELIM + "builtin" + DIR_DELIM; + lua_pushstring(L, path.c_str()); return 1; } @@ -358,6 +372,7 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(get_node_def); API_FCT(get_privilege_list); API_FCT(get_builtin_path); + API_FCT(get_true_builtin_path); API_FCT(get_language); API_FCT(get_csm_restrictions); } diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index e960dc4cf..c98e1bc9f 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -86,6 +86,9 @@ class ModApiClient : public ModApiBase // get_builtin_path() static int l_get_builtin_path(lua_State *L); + + // get_true_builtin_path() + static int l_get_true_builtin_path(lua_State *L); // get_csm_restrictions() static int l_get_csm_restrictions(lua_State *L); diff --git a/src/script/scripting_client.cpp b/src/script/scripting_client.cpp index 4e90079bd..5778aa08e 100644 --- a/src/script/scripting_client.cpp +++ b/src/script/scripting_client.cpp @@ -35,6 +35,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "lua_api/l_localplayer.h" #include "lua_api/l_camera.h" #include "lua_api/l_settings.h" +#include "lua_api/l_mainmenu.h" #include "lua_api/l_client_sound.h" ClientScripting::ClientScripting(Client *client): @@ -76,6 +77,7 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModChannelRef::Register(L); LuaSettings::Register(L); ClientSoundHandle::Register(L); + ModApiUtil::InitializeClient(L, top); ModApiClient::Initialize(L, top); @@ -85,6 +87,9 @@ void ClientScripting::InitializeModApi(lua_State *L, int top) ModApiChannels::Initialize(L, top); ModApiParticlesLocal::Initialize(L, top); ModApiClientSound::Initialize(L, top); + + ModApiMainMenu::Initialize(L, top); + } void ClientScripting::on_client_ready(LocalPlayer *localplayer) diff --git a/src/script/scripting_client.h b/src/script/scripting_client.h index 3088029f0..a34b269f1 100644 --- a/src/script/scripting_client.h +++ b/src/script/scripting_client.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "cpp_api/s_client.h" #include "cpp_api/s_modchannels.h" #include "cpp_api/s_security.h" +#include "cpp_api/s_mainmenu.h" class Client; class LocalPlayer; @@ -34,7 +35,8 @@ class ClientScripting: virtual public ScriptApiBase, public ScriptApiSecurity, public ScriptApiClient, - public ScriptApiModChannels + public ScriptApiModChannels, + public ScriptApiMainMenu { public: ClientScripting(Client *client); From a13cf23432c344c24a3002a3cf034488edb9b211 Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 01:33:26 -0400 Subject: [PATCH 4/9] Actually set settings --- builtin/client/pause_menu.lua | 2 +- builtin/mainmenu/settings/dlg_settings.lua | 4 ++-- src/client/game.cpp | 16 ++++++++++++++++ 3 files changed, 19 insertions(+), 3 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index da4158f09..f3c6a7206 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -109,5 +109,5 @@ end function core.show_settings() load(true, false) - show_settings_client_formspec() + show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS") end diff --git a/builtin/mainmenu/settings/dlg_settings.lua b/builtin/mainmenu/settings/dlg_settings.lua index 76eee8fdb..053cde2e9 100644 --- a/builtin/mainmenu/settings/dlg_settings.lua +++ b/builtin/mainmenu/settings/dlg_settings.lua @@ -756,6 +756,6 @@ function create_settings_dlg() return dlg end -function show_settings_client_formspec() - minetest.show_formspec("dlg_settings", get_formspec({})) +function show_settings_client_formspec(name) + minetest.show_formspec(name or "dlg_settings", get_formspec({})) end diff --git a/src/client/game.cpp b/src/client/game.cpp index 30a01fe51..c71b19c6b 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -189,6 +189,20 @@ struct LocalFormspecHandler : public TextDest return; } + + if (m_formname == "MT_PAUSE_MENU_SETTINGS") + { + // Loop through settings + for (auto i : fields) + { + if (g_settings->existsLocal(i.first) && g_settings->get(i.first) != i.second) + { + g_settings->set(i.first, i.second); + //std::cout << "Setting " << i.first << " set!" << std::endl; + } + } + return; + } if (m_formname == "MT_DEATH_SCREEN") { assert(m_client != nullptr); @@ -1880,6 +1894,7 @@ inline bool Game::handleCallbacks() (new GUIKeyChangeMenu(guienv, guiroot, -1, &g_menumgr, texture_src))->drop(); g_gamecallback->keyconfig_requested = false; + m_is_paused = false; } if (g_gamecallback->unpause_requested) { @@ -1891,6 +1906,7 @@ inline bool Game::handleCallbacks() if (client->modsLoaded()) { client->getScript()->show_settings(); + m_is_paused = false; } g_gamecallback->show_settings_requested = false; } From 96ea24ffefb00f13cd6b942f01c9c88592b2f35d Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 02:06:36 -0400 Subject: [PATCH 5/9] Switch between pages --- builtin/client/pause_menu.lua | 11 ++++++++--- builtin/mainmenu/settings/dlg_settings.lua | 4 ++-- src/client/game.cpp | 8 +++++++- src/script/cpp_api/s_client.cpp | 11 +++++++++-- src/script/cpp_api/s_client.h | 2 +- 5 files changed, 27 insertions(+), 9 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index f3c6a7206..bd867374e 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -107,7 +107,12 @@ function dialog_create(name, spec, buttonhandler, eventhandler) minetest.show_formspec(name, spec({})) end -function core.show_settings() - load(true, false) - show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS") +load(true, false) + +function core.show_settings(page_id) + if not page_id then + show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS", {}) + else + show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS", {page_id = page_id}) + end end diff --git a/builtin/mainmenu/settings/dlg_settings.lua b/builtin/mainmenu/settings/dlg_settings.lua index 053cde2e9..d8a96a1fb 100644 --- a/builtin/mainmenu/settings/dlg_settings.lua +++ b/builtin/mainmenu/settings/dlg_settings.lua @@ -756,6 +756,6 @@ function create_settings_dlg() return dlg end -function show_settings_client_formspec(name) - minetest.show_formspec(name or "dlg_settings", get_formspec({})) +function show_settings_client_formspec(name, data) + minetest.show_formspec(name or "dlg_settings", get_formspec(data)) end diff --git a/src/client/game.cpp b/src/client/game.cpp index c71b19c6b..62949b489 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -198,8 +198,14 @@ struct LocalFormspecHandler : public TextDest if (g_settings->existsLocal(i.first) && g_settings->get(i.first) != i.second) { g_settings->set(i.first, i.second); - //std::cout << "Setting " << i.first << " set!" << std::endl; } + if (i.first.rfind("page_", 0) == 0) + { + m_client->getScript()->show_settings(i.first.substr(5)); + std::cout << "Found ..." << m_client << std::endl; + } + //std::cout << "Setting " << i.first << " set!" << std::endl; + } return; } diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 5af8758d4..32db7a528 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -310,7 +310,7 @@ void ScriptApiClient::show_pause_menu(bool is_singleplayer, bool is_touchscreen, lua_pop(L, 1); } -void ScriptApiClient::show_settings() +void ScriptApiClient::show_settings(const std::string& page) { SCRIPTAPI_PRECHECKHEADER @@ -319,7 +319,14 @@ void ScriptApiClient::show_settings() lua_getglobal(L, "core"); lua_getfield(L, -1, "show_settings"); - PCALL_RES(lua_pcall(L, 0, 0, error_handler)); + if (page != "") + { + lua_pushstring(L, page.c_str()); + } + else + lua_pushnil(L); + + PCALL_RES(lua_pcall(L, 1, 0, error_handler)); lua_pop(L, 1); } diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index 61efa40bd..c0f8a4196 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -61,7 +61,7 @@ class ScriptApiClient : virtual public ScriptApiBase bool on_inventory_open(Inventory *inventory); void show_pause_menu(bool is_singleplayer, bool is_touchscreen, const std::string& server_address); - void show_settings(); + void show_settings(const std::string& page = ""); void setEnv(ClientEnvironment *env); }; From 1f52edb14ce7cbc468dfd51c4f52976cbacdbd2f Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 02:41:15 -0400 Subject: [PATCH 6/9] Live FOV changes Probably should add a method for changing the FOV but I am tired. This also works with /set fov ###, so not sure why something like this isn't done already. --- src/client/camera.h | 2 ++ src/client/game.cpp | 9 +++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/client/camera.h b/src/client/camera.h index 88533181b..0c432ac8d 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -228,7 +228,9 @@ class Camera Client *m_client; // Default Client FOV (as defined by the "fov" setting) +public: // TODO make a setter f32 m_cache_fov; +private: // Absolute camera position v3f m_camera_position; diff --git a/src/client/game.cpp b/src/client/game.cpp index 62949b489..68ce6067d 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -202,7 +202,6 @@ struct LocalFormspecHandler : public TextDest if (i.first.rfind("page_", 0) == 0) { m_client->getScript()->show_settings(i.first.substr(5)); - std::cout << "Found ..." << m_client << std::endl; } //std::cout << "Setting " << i.first << " set!" << std::endl; @@ -1041,6 +1040,8 @@ Game::Game() : &settingChangedCallback, this); g_settings->registerChangedCallback("pause_on_lost_focus", &settingChangedCallback, this); + g_settings->registerChangedCallback("fov", + &settingChangedCallback, this); readSettings(); } @@ -4441,13 +4442,17 @@ void Game::readSettings() m_cache_enable_noclip = g_settings->getBool("noclip"); m_cache_enable_free_move = g_settings->getBool("free_move"); + m_cache_cam_smoothing = 0; if (g_settings->getBool("cinematic")) m_cache_cam_smoothing = 1 - g_settings->getFloat("cinematic_camera_smoothing"); else m_cache_cam_smoothing = 1 - g_settings->getFloat("camera_smoothing"); - + + if (camera) + camera->m_cache_fov = g_settings->getFloat("fov"); + m_cache_cam_smoothing = rangelim(m_cache_cam_smoothing, 0.01f, 1.0f); m_cache_mouse_sensitivity = rangelim(m_cache_mouse_sensitivity, 0.001, 100.0); From 4b74e8d07134abfb9d8279f690a0c70547571191 Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 10:58:14 -0400 Subject: [PATCH 7/9] Move pause formspec events to Lua --- builtin/client/pause_menu.lua | 27 ++++++++++++- builtin/mainmenu/settings/dlg_settings.lua | 2 +- src/client/game.cpp | 45 +--------------------- src/script/cpp_api/s_client.cpp | 11 +----- src/script/cpp_api/s_client.h | 2 +- src/script/lua_api/l_client.cpp | 27 +++++++++++++ src/script/lua_api/l_client.h | 9 +++++ 7 files changed, 68 insertions(+), 55 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index bd867374e..873588437 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -88,9 +88,27 @@ Menu/inventory open: end function core.show_pause_menu(is_singleplayer, is_touchscreen, address) - minetest.show_formspec("MT_PAUSE_MENU", menu_formspec(is_singleplayer, is_touchscreen, address)) + minetest.show_formspec("builtin:MT_PAUSE_MENU", menu_formspec(is_singleplayer, is_touchscreen, address)) end +core.register_on_formspec_input(function(formname, fields) + if formname ~= "builtin:MT_PAUSE_MENU" then return end + + if fields.btn_continue then + core.unpause() + elseif fields.btn_key_config then + core.key_config() -- Don't want this + elseif fields.btn_change_password then + core.change_password() + elseif fields.btn_exit_menu then + core.disconnect() + elseif fields.btn_exit_os then + core.exit_to_os() + end + + minetest.log(dump(fields)) +end) + local scriptpath = core.get_builtin_path() local path = scriptpath.."mainmenu"..DIR_DELIM.."settings" @@ -109,6 +127,13 @@ end load(true, false) +local data = {data = {}} +core.register_on_formspec_input(function(formname, fields) + local this = data + --buttonhandler(this, fields) +end) + + function core.show_settings(page_id) if not page_id then show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS", {}) diff --git a/builtin/mainmenu/settings/dlg_settings.lua b/builtin/mainmenu/settings/dlg_settings.lua index d8a96a1fb..71483d915 100644 --- a/builtin/mainmenu/settings/dlg_settings.lua +++ b/builtin/mainmenu/settings/dlg_settings.lua @@ -633,7 +633,7 @@ function write_settings_early() end -local function buttonhandler(this, fields) +function buttonhandler(this, fields) local dialogdata = this.data dialogdata.leftscroll = core.explode_scrollbar_event(fields.leftscroll).value or dialogdata.leftscroll dialogdata.rightscroll = core.explode_scrollbar_event(fields.rightscroll).value or dialogdata.rightscroll diff --git a/src/client/game.cpp b/src/client/game.cpp index 68ce6067d..2fa1e2fb3 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -149,48 +149,7 @@ struct LocalFormspecHandler : public TextDest void gotText(const StringMap &fields) { - if (m_formname == "MT_PAUSE_MENU") { - if (fields.find("btn_sound") != fields.end()) { - g_gamecallback->changeVolume(); - return; - } - - else if (fields.find("btn_key_config") != fields.end()) { - g_gamecallback->keyConfig(); - return; - } - - else if (fields.find("btn_settings") != fields.end()) { - g_gamecallback->showSettings(); - } - - else if (fields.find("btn_exit_menu") != fields.end()) { - g_gamecallback->disconnect(); - return; - } - - else if (fields.find("btn_exit_os") != fields.end()) { - g_gamecallback->exitToOS(); -#ifndef __ANDROID__ - RenderingEngine::get_raw_device()->closeDevice(); -#endif - return; - } - - else if (fields.find("btn_change_password") != fields.end()) { - g_gamecallback->changePassword(); - return; - } - - else { - g_gamecallback->unpause(); - return; - } - - return; - } - - if (m_formname == "MT_PAUSE_MENU_SETTINGS") + if (m_formname == "MT_PAUSE_MENU_SETTINGS" && false) { // Loop through settings for (auto i : fields) @@ -201,7 +160,7 @@ struct LocalFormspecHandler : public TextDest } if (i.first.rfind("page_", 0) == 0) { - m_client->getScript()->show_settings(i.first.substr(5)); + //m_client->getScript()->show_settings(i.first.substr(5)); } //std::cout << "Setting " << i.first << " set!" << std::endl; diff --git a/src/script/cpp_api/s_client.cpp b/src/script/cpp_api/s_client.cpp index 32db7a528..5af8758d4 100644 --- a/src/script/cpp_api/s_client.cpp +++ b/src/script/cpp_api/s_client.cpp @@ -310,7 +310,7 @@ void ScriptApiClient::show_pause_menu(bool is_singleplayer, bool is_touchscreen, lua_pop(L, 1); } -void ScriptApiClient::show_settings(const std::string& page) +void ScriptApiClient::show_settings() { SCRIPTAPI_PRECHECKHEADER @@ -319,14 +319,7 @@ void ScriptApiClient::show_settings(const std::string& page) lua_getglobal(L, "core"); lua_getfield(L, -1, "show_settings"); - if (page != "") - { - lua_pushstring(L, page.c_str()); - } - else - lua_pushnil(L); - - PCALL_RES(lua_pcall(L, 1, 0, error_handler)); + PCALL_RES(lua_pcall(L, 0, 0, error_handler)); lua_pop(L, 1); } diff --git a/src/script/cpp_api/s_client.h b/src/script/cpp_api/s_client.h index c0f8a4196..61efa40bd 100644 --- a/src/script/cpp_api/s_client.h +++ b/src/script/cpp_api/s_client.h @@ -61,7 +61,7 @@ class ScriptApiClient : virtual public ScriptApiBase bool on_inventory_open(Inventory *inventory); void show_pause_menu(bool is_singleplayer, bool is_touchscreen, const std::string& server_address); - void show_settings(const std::string& page = ""); + void show_settings(); void setEnv(ClientEnvironment *env); }; diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 912e212af..9d6cdf383 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -23,6 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "client/client.h" #include "client/clientevent.h" #include "client/sound.h" +#include "client/renderingengine.h" #include "client/clientenvironment.h" #include "common/c_content.h" #include "common/c_converter.h" @@ -178,6 +179,29 @@ int ModApiClient::l_disconnect(lua_State *L) return 1; } +// unpause() +int ModApiClient::l_unpause(lua_State *L) +{ + g_gamecallback->unpause(); + //lua_pushboolean(L, true); + return 1; +} + +int ModApiClient::l_exit_to_os(lua_State *L) +{ + g_gamecallback->exitToOS(); +#ifndef __ANDROID__ + RenderingEngine::get_raw_device()->closeDevice(); +#endif + return 1; +} + +int ModApiClient::l_key_config(lua_State *L) +{ + g_gamecallback->keyConfig(); + return 1; +} + // gettext(text) int ModApiClient::l_gettext(lua_State *L) { @@ -366,6 +390,9 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(gettext); API_FCT(get_node_or_nil); API_FCT(disconnect); + API_FCT(unpause); + API_FCT(exit_to_os); + API_FCT(key_config); API_FCT(get_meta); API_FCT(get_server_info); API_FCT(get_item_def); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index c98e1bc9f..7f93d66ce 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -50,6 +50,15 @@ class ModApiClient : public ModApiBase // show_formspec(name, formspec) static int l_show_formspec(lua_State *L); + + // unpause() + static int l_unpause(lua_State *L); + + // exit_to_os() + static int l_exit_to_os(lua_State *L); + + // key_config() + static int l_key_config(lua_State *L); // send_respawn() static int l_send_respawn(lua_State *L); From b8959a0bac410cfe116ea13442248d470fac9b90 Mon Sep 17 00:00:00 2001 From: swagtoy Date: Thu, 27 Jun 2024 12:27:58 -0400 Subject: [PATCH 8/9] Settings formspec demonstration This is really hacky, but it demonstrates that everything works (kinda) --- builtin/client/pause_menu.lua | 139 +++++++++++++++++++-- builtin/mainmenu/settings/dlg_settings.lua | 16 ++- 2 files changed, 138 insertions(+), 17 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index 873588437..8908954f8 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -100,13 +100,15 @@ core.register_on_formspec_input(function(formname, fields) core.key_config() -- Don't want this elseif fields.btn_change_password then core.change_password() + elseif fields.btn_settings then + core.show_settings() elseif fields.btn_exit_menu then core.disconnect() elseif fields.btn_exit_os then core.exit_to_os() end - minetest.log(dump(fields)) + return end) local scriptpath = core.get_builtin_path() @@ -125,19 +127,134 @@ function dialog_create(name, spec, buttonhandler, eventhandler) minetest.show_formspec(name, spec({})) end -load(true, false) -local data = {data = {}} +local settings_data = {} +settings_data.data = { + leftscroll = 0, + query = "", + rightscroll = 0, + components = {}, + page_id = "accessibility" +} + core.register_on_formspec_input(function(formname, fields) - local this = data - --buttonhandler(this, fields) + if formname ~= "builtin:MT_PAUSE_MENU_SETTINGS" then return true end + --local this = data + --buttonhandler(settings_data, fields) + local dialogdata = settings_data.data + dialogdata.leftscroll = core.explode_scrollbar_event(fields.leftscroll).value or dialogdata.leftscroll + dialogdata.rightscroll = core.explode_scrollbar_event(fields.rightscroll).value or dialogdata.rightscroll + dialogdata.query = fields.search_query + local update = false + + if fields.back then + this:delete() + return true + end + + if fields.show_technical_names ~= nil then + local value = core.is_yes(fields.show_technical_names) + core.settings:set_bool("show_technical_names", value) + write_settings_early() + update = true + --return true + end + + if fields.show_advanced ~= nil then + local value = core.is_yes(fields.show_advanced) + core.settings:set_bool("show_advanced", value) + write_settings_early() + core.show_settings() + update = true + end + + -- enable_touch is a checkbox in a setting component. We handle this + -- setting differently so we can hide/show pages using the next if-statement + if fields.enable_touch ~= nil then + local value = core.is_yes(fields.enable_touch) + core.settings:set_bool("enable_touch", value) + write_settings_early() + core.show_settings() + update = true + end + + if fields.show_advanced ~= nil or fields.enable_touch ~= nil then + local suggested_page_id = update_filtered_pages(dialogdata.query) + + dialogdata.components = nil + + if not filtered_page_by_id[dialogdata.page_id] then + dialogdata.leftscroll = 0 + dialogdata.rightscroll = 0 + + dialogdata.page_id = suggested_page_id + end + + return true + end + + if fields.search or fields.key_enter_field == "search_query" then + dialogdata.components = nil + dialogdata.leftscroll = 0 + dialogdata.rightscroll = 0 + + dialogdata.page_id = update_filtered_pages(dialogdata.query) + + return true + end + if fields.search_clear then + dialogdata.query = "" + dialogdata.components = nil + dialogdata.leftscroll = 0 + dialogdata.rightscroll = 0 + + dialogdata.page_id = update_filtered_pages("") + return true + end + + for _, page in ipairs(all_pages) do + if fields["page_" .. page.id] then + dialogdata.page_id = page.id + dialogdata.components = nil + dialogdata.rightscroll = 0 + core.show_settings() + return true + end + end + + if dialogdata.components then + for i, comp in ipairs(dialogdata.components) do + if comp.on_submit and comp:on_submit(fields, this) then + write_settings_early() + core.show_settings() + + -- Clear components so they regenerate + --dialogdata.components = nil + return true + end + if comp.setting and fields["reset_" .. i] then + core.settings:remove(comp.setting.name) + write_settings_early() + core.show_settings() + + -- Clear components so they regenerate + --dialogdata.components = nil + return true + end + end + end + + if update then + core.show_settings() + end + + return false end) +load(true, false) +--settings_data.data.page_id = update_filtered_pages("") -function core.show_settings(page_id) - if not page_id then - show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS", {}) - else - show_settings_client_formspec("MT_PAUSE_MENU_SETTINGS", {page_id = page_id}) - end +function core.show_settings() + show_settings_client_formspec("builtin:MT_PAUSE_MENU_SETTINGS", settings_data.data) + core.unpause() end diff --git a/builtin/mainmenu/settings/dlg_settings.lua b/builtin/mainmenu/settings/dlg_settings.lua index 71483d915..d9691d13b 100644 --- a/builtin/mainmenu/settings/dlg_settings.lua +++ b/builtin/mainmenu/settings/dlg_settings.lua @@ -23,13 +23,13 @@ local shadows_component = dofile(core.get_mainmenu_path() .. DIR_DELIM .. "settings" .. DIR_DELIM .. "shadows_component.lua") local loaded = false -local full_settings + full_settings = {} local info_icon_path = core.formspec_escape(defaulttexturedir .. "settings_info.png") local reset_icon_path = core.formspec_escape(defaulttexturedir .. "settings_reset.png") -local all_pages = {} -local page_by_id = {} -local filtered_pages = all_pages -local filtered_page_by_id = page_by_id + all_pages = {} + page_by_id = {} + filtered_pages = all_pages + filtered_page_by_id = page_by_id local function get_setting_info(name) @@ -288,7 +288,7 @@ local function filter_page_content(page, query_keywords) end -local function update_filtered_pages(query) +function update_filtered_pages(query) filtered_pages = {} filtered_page_by_id = {} @@ -638,6 +638,8 @@ function buttonhandler(this, fields) dialogdata.leftscroll = core.explode_scrollbar_event(fields.leftscroll).value or dialogdata.leftscroll dialogdata.rightscroll = core.explode_scrollbar_event(fields.rightscroll).value or dialogdata.rightscroll dialogdata.query = fields.search_query + + minetest.log(dump(fields)) if fields.back then this:delete() @@ -709,6 +711,7 @@ function buttonhandler(this, fields) end end + if dialogdata.components then for i, comp in ipairs(dialogdata.components) do if comp.on_submit and comp:on_submit(fields, this) then write_settings_early() @@ -726,6 +729,7 @@ function buttonhandler(this, fields) return true end end + end return false end From b2792e59f735376889de310d844efeac49a7649a Mon Sep 17 00:00:00 2001 From: swagtoy Date: Fri, 28 Jun 2024 01:31:37 -0400 Subject: [PATCH 9/9] Reload graphics & dynamic shadows You can force reload graphics by showing the verbose debug page (press F5 a few times). It might be better to bind it to a specific keybind, but this was easier to implement and didn't require taking up another keybind. --- builtin/client/pause_menu.lua | 1 + src/client/clientenvironment.cpp | 6 ++++++ src/client/clientenvironment.h | 6 ++++-- src/client/clientobject.h | 1 + src/client/content_cao.cpp | 13 +++++++++++++ src/client/content_cao.h | 1 + src/client/game.cpp | 18 ++++++++++++++++++ src/client/render/factory.cpp | 2 +- src/gui/mainmenumanager.h | 7 +++++++ src/script/lua_api/l_client.cpp | 7 +++++++ src/script/lua_api/l_client.h | 3 +++ 11 files changed, 62 insertions(+), 3 deletions(-) diff --git a/builtin/client/pause_menu.lua b/builtin/client/pause_menu.lua index 8908954f8..7d2481ded 100644 --- a/builtin/client/pause_menu.lua +++ b/builtin/client/pause_menu.lua @@ -218,6 +218,7 @@ core.register_on_formspec_input(function(formname, fields) dialogdata.components = nil dialogdata.rightscroll = 0 core.show_settings() + core.reload_graphics() return true end end diff --git a/src/client/clientenvironment.cpp b/src/client/clientenvironment.cpp index 7e1676ffe..7d38b538c 100644 --- a/src/client/clientenvironment.cpp +++ b/src/client/clientenvironment.cpp @@ -273,6 +273,9 @@ void ClientEnvironment::step(float dtime) auto cb_state = [this, dtime, update_lighting, day_night_ratio] (ClientActiveObject *cao) { // Step object cao->step(dtime, this); + + if (m_update_shadows) + cao->updateSceneShadows(); if (update_lighting) cao->updateLight(day_night_ratio); @@ -296,6 +299,9 @@ void ClientEnvironment::step(float dtime) ++i; } } + + if (m_update_shadows) + m_update_shadows = false; } void ClientEnvironment::addSimpleObject(ClientSimpleObject *simple) diff --git a/src/client/clientenvironment.h b/src/client/clientenvironment.h index bdb8b9726..8f6e4350b 100644 --- a/src/client/clientenvironment.h +++ b/src/client/clientenvironment.h @@ -142,13 +142,14 @@ class ClientEnvironment : public Environment const std::set &getPlayerNames() { return m_player_names; } void addPlayerName(const std::string &name) { m_player_names.insert(name); } void removePlayerName(const std::string &name) { m_player_names.erase(name); } - void updateCameraOffset(const v3s16 &camera_offset) - { m_camera_offset = camera_offset; } + void updateCameraOffset(const v3s16 &camera_offset) { m_camera_offset = camera_offset; } + void requestUpdateShadows() { m_update_shadows = true; } v3s16 getCameraOffset() const { return m_camera_offset; } void updateFrameTime(bool is_paused); u64 getFrameTime() const { return m_frame_time; } u64 getFrameTimeDelta() const { return m_frame_dtime; } + private: ClientMap *m_map; @@ -162,6 +163,7 @@ class ClientEnvironment : public Environment IntervalLimiter m_active_object_light_update_interval; std::set m_player_names; v3s16 m_camera_offset; + bool m_update_shadows = false; u64 m_frame_time = 0; u64 m_frame_dtime = 0; u64 m_frame_time_pause_accumulator = 0; diff --git a/src/client/clientobject.h b/src/client/clientobject.h index f63681313..83ef1e346 100644 --- a/src/client/clientobject.h +++ b/src/client/clientobject.h @@ -62,6 +62,7 @@ class ClientActiveObject : public ActiveObject virtual void updateAttachments() {}; virtual bool doShowSelectionBox() { return true; } + virtual void updateSceneShadows() {} // Step object in time virtual void step(float dtime, ClientEnvironment *env) {} diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index 0044cc16e..e0207719a 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -604,6 +604,17 @@ void GenericCAO::removeFromScene(bool permanent) m_client->getMinimap()->removeMarker(&m_marker); } +void GenericCAO::updateSceneShadows() +{ + if (scene::ISceneNode *node = getSceneNode()) { + if (m_matrixnode) + node->setParent(m_matrixnode); + + if (auto shadow = RenderingEngine::get_shadow_renderer()) + shadow->addNodeToShadowList(node); + } +} + void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) { m_smgr = smgr; @@ -833,6 +844,8 @@ void GenericCAO::addToScene(ITextureSource *tsrc, scene::ISceneManager *smgr) if (m_reset_textures_timer < 0) updateTextures(m_current_texture_modifier); + + if (scene::ISceneNode *node = getSceneNode()) { if (m_matrixnode) node->setParent(m_matrixnode); diff --git a/src/client/content_cao.h b/src/client/content_cao.h index 7fdcb73da..8e3a507bb 100644 --- a/src/client/content_cao.h +++ b/src/client/content_cao.h @@ -249,6 +249,7 @@ class GenericCAO : public ClientActiveObject } void updateLight(u32 day_night_ratio) override; + void updateSceneShadows() override; void setNodeLight(const video::SColor &light); diff --git a/src/client/game.cpp b/src/client/game.cpp index 2fa1e2fb3..8cbfc59e2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -739,6 +739,7 @@ class Game { void updateCameraOrientation(CameraOrientation *cam, float dtime); void updatePlayerControl(const CameraOrientation &cam); void updatePauseState(); + void reloadGraphics(); void step(f32 dtime); void processClientEvents(CameraOrientation *cam); void updateCamera(f32 dtime); @@ -1126,6 +1127,12 @@ bool Game::startup(bool *kill, return true; } +inline void Game::reloadGraphics() +{ + m_rendering_engine->initialize(client, hud); + client->getEnv().requestUpdateShadows(); + +} void Game::run() { @@ -1802,6 +1809,8 @@ bool Game::getServerContent(bool *aborted) } + + /****************************************************************************/ /**************************************************************************** Run @@ -1865,9 +1874,15 @@ inline bool Game::handleCallbacks() if (g_gamecallback->unpause_requested) { m_is_paused = false; + m_rendering_engine->initialize(client, hud); g_gamecallback->unpause_requested = false; } + if (g_gamecallback->reload_graphics_requested) { + reloadGraphics(); + g_gamecallback->reload_graphics_requested = false; + } + if (g_gamecallback->show_settings_requested) { if (client->modsLoaded()) { @@ -1911,7 +1926,9 @@ void Game::updateDebugState() m_game_ui->m_flags.show_basic_debug = false; } else if (m_game_ui->m_flags.show_minimal_debug) { if (has_basic_debug) + { m_game_ui->m_flags.show_basic_debug = true; + } } if (!has_basic_debug) hud->disableBlockBounds(); @@ -2523,6 +2540,7 @@ void Game::toggleDebug() } else if (!m_game_ui->m_flags.show_profiler_graph && !draw_control->show_wireframe) { if (has_basic_debug) m_game_ui->m_flags.show_basic_debug = true; + reloadGraphics(); m_game_ui->m_flags.show_profiler_graph = true; m_game_ui->showTranslatedStatusText("Profiler graph shown"); } else if (!draw_control->show_wireframe && client->checkPrivilege("debug")) { diff --git a/src/client/render/factory.cpp b/src/client/render/factory.cpp index 2e9d5eb5f..dbb33e9f3 100644 --- a/src/client/render/factory.cpp +++ b/src/client/render/factory.cpp @@ -82,4 +82,4 @@ void createPipeline(const std::string &stereo_mode, IrrlichtDevice *device, Clie // fallback to plain renderer errorstream << "Invalid rendering mode: " << stereo_mode << std::endl; populatePlainPipeline(result.pipeline, client); -} \ No newline at end of file +} diff --git a/src/gui/mainmenumanager.h b/src/gui/mainmenumanager.h index 06c8d22c2..08c5a9242 100644 --- a/src/gui/mainmenumanager.h +++ b/src/gui/mainmenumanager.h @@ -35,6 +35,7 @@ class IGameCallback virtual void changePassword() = 0; virtual void changeVolume() = 0; virtual void unpause() = 0; + virtual void reloadGraphics() = 0; virtual void showSettings() = 0; virtual void showOpenURLDialog(const std::string &url) = 0; virtual void signalKeyConfigChange() = 0; @@ -154,6 +155,11 @@ class MainGameCallback : public IGameCallback unpause_requested = true; } + void reloadGraphics() override + { + reload_graphics_requested = true; + } + void showSettings() override { show_settings_requested = true; @@ -165,6 +171,7 @@ class MainGameCallback : public IGameCallback bool keyconfig_requested = false; bool shutdown_requested = false; bool unpause_requested = false; + bool reload_graphics_requested = false; bool show_settings_requested = false; bool keyconfig_changed = false; std::string show_open_url_dialog = ""; diff --git a/src/script/lua_api/l_client.cpp b/src/script/lua_api/l_client.cpp index 9d6cdf383..110426ad6 100644 --- a/src/script/lua_api/l_client.cpp +++ b/src/script/lua_api/l_client.cpp @@ -196,6 +196,12 @@ int ModApiClient::l_exit_to_os(lua_State *L) return 1; } +int ModApiClient::l_reload_graphics(lua_State *L) +{ + g_gamecallback->reloadGraphics(); + return 1; +} + int ModApiClient::l_key_config(lua_State *L) { g_gamecallback->keyConfig(); @@ -392,6 +398,7 @@ void ModApiClient::Initialize(lua_State *L, int top) API_FCT(disconnect); API_FCT(unpause); API_FCT(exit_to_os); + API_FCT(reload_graphics); API_FCT(key_config); API_FCT(get_meta); API_FCT(get_server_info); diff --git a/src/script/lua_api/l_client.h b/src/script/lua_api/l_client.h index 7f93d66ce..b26faa5a4 100644 --- a/src/script/lua_api/l_client.h +++ b/src/script/lua_api/l_client.h @@ -57,6 +57,9 @@ class ModApiClient : public ModApiBase // exit_to_os() static int l_exit_to_os(lua_State *L); + // reload_graphics() + static int l_reload_graphics(lua_State *L); + // key_config() static int l_key_config(lua_State *L);