mirror of
https://github.com/luanti-org/luanti.git
synced 2025-08-01 17:38:41 +00:00
In-game settings menu using separate Lua environment (#15614)
This commit is contained in:
parent
3cb07d5fb6
commit
eeb6cab4c4
48 changed files with 652 additions and 290 deletions
|
@ -9,6 +9,7 @@
|
|||
#include "renderingengine.h"
|
||||
#include "client.h"
|
||||
#include "scripting_client.h"
|
||||
#include "cpp_api/s_client_common.h"
|
||||
#include "clientmap.h"
|
||||
#include "gui/guiFormSpecMenu.h"
|
||||
#include "gui/mainmenumanager.h"
|
||||
|
@ -70,69 +71,73 @@ struct TextDestPlayerInventory : public TextDest
|
|||
Client *m_client;
|
||||
};
|
||||
|
||||
struct LocalFormspecHandler : public TextDest
|
||||
struct LocalScriptingFormspecHandler : public TextDest
|
||||
{
|
||||
LocalFormspecHandler(const std::string &formname)
|
||||
{
|
||||
m_formname = formname;
|
||||
}
|
||||
|
||||
LocalFormspecHandler(const std::string &formname, Client *client):
|
||||
m_client(client)
|
||||
LocalScriptingFormspecHandler(const std::string &formname, ScriptApiClientCommon *script)
|
||||
{
|
||||
m_formname = formname;
|
||||
m_script = script;
|
||||
}
|
||||
|
||||
void gotText(const StringMap &fields)
|
||||
{
|
||||
if (m_formname == "MT_PAUSE_MENU") {
|
||||
if (fields.find("btn_sound") != fields.end()) {
|
||||
g_gamecallback->changeVolume();
|
||||
return;
|
||||
}
|
||||
m_script->on_formspec_input(m_formname, fields);
|
||||
}
|
||||
|
||||
if (fields.find("btn_key_config") != fields.end()) {
|
||||
g_gamecallback->keyConfig();
|
||||
return;
|
||||
}
|
||||
ScriptApiClientCommon *m_script = nullptr;
|
||||
};
|
||||
|
||||
if (fields.find("btn_touchscreen_layout") != fields.end()) {
|
||||
g_gamecallback->touchscreenLayout();
|
||||
return;
|
||||
}
|
||||
struct HardcodedPauseFormspecHandler : public TextDest
|
||||
{
|
||||
HardcodedPauseFormspecHandler()
|
||||
{
|
||||
m_formname = "MT_PAUSE_MENU";
|
||||
}
|
||||
|
||||
if (fields.find("btn_exit_menu") != fields.end()) {
|
||||
g_gamecallback->disconnect();
|
||||
return;
|
||||
}
|
||||
void gotText(const StringMap &fields)
|
||||
{
|
||||
if (fields.find("btn_settings") != fields.end()) {
|
||||
g_gamecallback->openSettings();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields.find("btn_exit_os") != fields.end()) {
|
||||
g_gamecallback->exitToOS();
|
||||
if (fields.find("btn_sound") != fields.end()) {
|
||||
g_gamecallback->changeVolume();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields.find("btn_exit_menu") != fields.end()) {
|
||||
g_gamecallback->disconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields.find("btn_exit_os") != fields.end()) {
|
||||
g_gamecallback->exitToOS();
|
||||
#ifndef __ANDROID__
|
||||
RenderingEngine::get_raw_device()->closeDevice();
|
||||
RenderingEngine::get_raw_device()->closeDevice();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
|
||||
if (fields.find("btn_change_password") != fields.end()) {
|
||||
g_gamecallback->changePassword();
|
||||
return;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_formname == "MT_DEATH_SCREEN") {
|
||||
assert(m_client != nullptr);
|
||||
|
||||
if (fields.find("quit") != fields.end())
|
||||
m_client->sendRespawnLegacy();
|
||||
|
||||
if (fields.find("btn_change_password") != fields.end()) {
|
||||
g_gamecallback->changePassword();
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (m_client->modsLoaded())
|
||||
m_client->getScript()->on_formspec_input(m_formname, fields);
|
||||
struct LegacyDeathFormspecHandler : public TextDest
|
||||
{
|
||||
LegacyDeathFormspecHandler(Client *client)
|
||||
{
|
||||
m_formname = "MT_DEATH_SCREEN";
|
||||
m_client = client;
|
||||
}
|
||||
|
||||
void gotText(const StringMap &fields)
|
||||
{
|
||||
if (fields.find("quit") != fields.end())
|
||||
m_client->sendRespawnLegacy();
|
||||
}
|
||||
|
||||
Client *m_client = nullptr;
|
||||
|
@ -193,6 +198,15 @@ public:
|
|||
|
||||
//// GameFormSpec
|
||||
|
||||
void GameFormSpec::init(Client *client, RenderingEngine *rendering_engine, InputHandler *input)
|
||||
{
|
||||
m_client = client;
|
||||
m_rendering_engine = rendering_engine;
|
||||
m_input = input;
|
||||
m_pause_script = std::make_unique<PauseMenuScripting>(client);
|
||||
m_pause_script->loadBuiltin();
|
||||
}
|
||||
|
||||
void GameFormSpec::deleteFormspec()
|
||||
{
|
||||
if (m_formspec) {
|
||||
|
@ -208,35 +222,72 @@ GameFormSpec::~GameFormSpec() {
|
|||
this->deleteFormspec();
|
||||
}
|
||||
|
||||
void GameFormSpec::showFormSpec(const std::string &formspec, const std::string &formname)
|
||||
bool GameFormSpec::handleEmptyFormspec(const std::string &formspec, const std::string &formname)
|
||||
{
|
||||
if (formspec.empty()) {
|
||||
if (m_formspec && (formname.empty() || formname == m_formname)) {
|
||||
m_formspec->quitMenu();
|
||||
}
|
||||
} else {
|
||||
FormspecFormSource *fs_src =
|
||||
new FormspecFormSource(formspec);
|
||||
TextDestPlayerInventory *txt_dst =
|
||||
new TextDestPlayerInventory(m_client, formname);
|
||||
|
||||
m_formname = formname;
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
&m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(),
|
||||
m_client->getSoundManager());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void GameFormSpec::showLocalFormSpec(const std::string &formspec, const std::string &formname)
|
||||
void GameFormSpec::showFormSpec(const std::string &formspec, const std::string &formname)
|
||||
{
|
||||
if (handleEmptyFormspec(formspec, formname))
|
||||
return;
|
||||
|
||||
FormspecFormSource *fs_src =
|
||||
new FormspecFormSource(formspec);
|
||||
TextDestPlayerInventory *txt_dst =
|
||||
new TextDestPlayerInventory(m_client, formname);
|
||||
|
||||
m_formname = formname;
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
&m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(),
|
||||
m_client->getSoundManager());
|
||||
}
|
||||
|
||||
void GameFormSpec::showCSMFormSpec(const std::string &formspec, const std::string &formname)
|
||||
{
|
||||
if (handleEmptyFormspec(formspec, formname))
|
||||
return;
|
||||
|
||||
FormspecFormSource *fs_src = new FormspecFormSource(formspec);
|
||||
LocalFormspecHandler *txt_dst =
|
||||
new LocalFormspecHandler(formname, m_client);
|
||||
LocalScriptingFormspecHandler *txt_dst =
|
||||
new LocalScriptingFormspecHandler(formname, m_client->getScript());
|
||||
|
||||
m_formname = formname;
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
&m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(),
|
||||
m_client->getSoundManager());
|
||||
}
|
||||
|
||||
void GameFormSpec::showPauseMenuFormSpec(const std::string &formspec, const std::string &formname)
|
||||
{
|
||||
// The pause menu env is a trusted context like the mainmenu env and provides
|
||||
// the in-game settings formspec.
|
||||
// Neither CSM nor the server must be allowed to mess with it.
|
||||
|
||||
if (handleEmptyFormspec(formspec, formname))
|
||||
return;
|
||||
|
||||
FormspecFormSource *fs_src = new FormspecFormSource(formspec);
|
||||
LocalScriptingFormspecHandler *txt_dst =
|
||||
new LocalScriptingFormspecHandler(formname, m_pause_script.get());
|
||||
|
||||
m_formname = formname;
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
// Ignore formspec prepend.
|
||||
&m_input->joystick, fs_src, txt_dst, "",
|
||||
m_client->getSoundManager());
|
||||
|
||||
// FIXME: can't enable this for now because "fps_max_unfocused" also applies
|
||||
// when the game is paused, making the settings menu much less enjoyable.
|
||||
// m_formspec->doPause = true;
|
||||
}
|
||||
|
||||
void GameFormSpec::showNodeFormspec(const std::string &formspec, const v3s16 &nodepos)
|
||||
{
|
||||
infostream << "Launching custom inventory view" << std::endl;
|
||||
|
@ -331,6 +382,9 @@ void GameFormSpec::showPauseMenu()
|
|||
os << "field[4.95,0;5,1.5;;" << strgettext("Game paused") << ";]";
|
||||
}
|
||||
|
||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_settings;"
|
||||
<< strgettext("Settings") << "]";
|
||||
|
||||
#ifndef __ANDROID__
|
||||
#if USE_SOUND
|
||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_sound;"
|
||||
|
@ -338,13 +392,6 @@ void GameFormSpec::showPauseMenu()
|
|||
#endif
|
||||
#endif
|
||||
|
||||
if (g_touchcontrols) {
|
||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_touchscreen_layout;"
|
||||
<< strgettext("Touchscreen Layout") << "]";
|
||||
} else {
|
||||
os << "button_exit[4," << (ypos++) << ";3,0.5;btn_key_config;"
|
||||
<< strgettext("Controls") << "]";
|
||||
}
|
||||
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;"
|
||||
|
@ -394,13 +441,13 @@ void GameFormSpec::showPauseMenu()
|
|||
/* Note: FormspecFormSource and LocalFormspecHandler *
|
||||
* are deleted by guiFormSpecMenu */
|
||||
FormspecFormSource *fs_src = new FormspecFormSource(os.str());
|
||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_PAUSE_MENU");
|
||||
HardcodedPauseFormspecHandler *txt_dst = new HardcodedPauseFormspecHandler();
|
||||
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
&m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(),
|
||||
m_client->getSoundManager());
|
||||
m_formspec->setFocus("btn_continue");
|
||||
// game will be paused in next step, if in singleplayer (see m_is_paused)
|
||||
// game will be paused in next step, if in singleplayer (see Game::m_is_paused)
|
||||
m_formspec->doPause = true;
|
||||
}
|
||||
|
||||
|
@ -418,7 +465,7 @@ void GameFormSpec::showDeathFormspecLegacy()
|
|||
/* Note: FormspecFormSource and LocalFormspecHandler *
|
||||
* are deleted by guiFormSpecMenu */
|
||||
FormspecFormSource *fs_src = new FormspecFormSource(formspec_str);
|
||||
LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", m_client);
|
||||
LegacyDeathFormspecHandler *txt_dst = new LegacyDeathFormspecHandler(m_client);
|
||||
|
||||
GUIFormSpecMenu::create(m_formspec, m_client, m_rendering_engine->get_gui_env(),
|
||||
&m_input->joystick, fs_src, txt_dst, m_client->getFormspecPrepend(),
|
||||
|
@ -473,6 +520,11 @@ bool GameFormSpec::handleCallbacks()
|
|||
return false;
|
||||
}
|
||||
|
||||
if (g_gamecallback->settings_requested) {
|
||||
m_pause_script->open_settings();
|
||||
g_gamecallback->settings_requested = false;
|
||||
}
|
||||
|
||||
if (g_gamecallback->changepassword_requested) {
|
||||
(void)make_irr<GUIPasswordChange>(guienv, guiroot, -1,
|
||||
&g_menumgr, m_client, texture_src);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue