mirror of
				https://github.com/luanti-org/luanti.git
				synced 2025-11-04 01:05:48 +01:00 
			
		
		
		
	Move formspec code from game.cpp to separate file
This commit is contained in:
		@@ -51,6 +51,7 @@ set(client_SRCS
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/fontengine.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/game.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/gameui.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/game_formspec.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/guiscalingfilter.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/hud.cpp
 | 
			
		||||
	${CMAKE_CURRENT_SOURCE_DIR}/imagefilters.cpp
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,7 @@
 | 
			
		||||
#include "client.h"
 | 
			
		||||
#include "client/clientevent.h"
 | 
			
		||||
#include "client/gameui.h"
 | 
			
		||||
#include "client/game_formspec.h"
 | 
			
		||||
#include "client/inputhandler.h"
 | 
			
		||||
#include "client/texturepaths.h"
 | 
			
		||||
#include "client/keys.h"
 | 
			
		||||
@@ -26,18 +27,13 @@
 | 
			
		||||
#include "client/event_manager.h"
 | 
			
		||||
#include "fontengine.h"
 | 
			
		||||
#include "gui/touchcontrols.h"
 | 
			
		||||
#include "gui/touchscreeneditor.h"
 | 
			
		||||
#include "itemdef.h"
 | 
			
		||||
#include "log.h"
 | 
			
		||||
#include "log_internal.h"
 | 
			
		||||
#include "gameparams.h"
 | 
			
		||||
#include "gettext.h"
 | 
			
		||||
#include "gui/guiChatConsole.h"
 | 
			
		||||
#include "gui/guiFormSpecMenu.h"
 | 
			
		||||
#include "gui/guiKeyChangeMenu.h"
 | 
			
		||||
#include "gui/guiPasswordChange.h"
 | 
			
		||||
#include "gui/guiOpenURL.h"
 | 
			
		||||
#include "gui/guiVolumeChange.h"
 | 
			
		||||
#include "texturesource.h"
 | 
			
		||||
#include "gui/mainmenumanager.h"
 | 
			
		||||
#include "gui/profilergraph.h"
 | 
			
		||||
#include "minimap.h"
 | 
			
		||||
@@ -69,176 +65,6 @@
 | 
			
		||||
	#include "client/sound/sound_openal.h"
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	Text input system
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
struct TextDestNodeMetadata : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	TextDestNodeMetadata(v3s16 p, Client *client)
 | 
			
		||||
	{
 | 
			
		||||
		m_p = p;
 | 
			
		||||
		m_client = client;
 | 
			
		||||
	}
 | 
			
		||||
	// This is deprecated I guess? -celeron55
 | 
			
		||||
	void gotText(const std::wstring &text)
 | 
			
		||||
	{
 | 
			
		||||
		std::string ntext = wide_to_utf8(text);
 | 
			
		||||
		infostream << "Submitting 'text' field of node at (" << m_p.X << ","
 | 
			
		||||
			   << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
 | 
			
		||||
		StringMap fields;
 | 
			
		||||
		fields["text"] = ntext;
 | 
			
		||||
		m_client->sendNodemetaFields(m_p, "", fields);
 | 
			
		||||
	}
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		m_client->sendNodemetaFields(m_p, "", fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v3s16 m_p;
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct TextDestPlayerInventory : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	TextDestPlayerInventory(Client *client)
 | 
			
		||||
	{
 | 
			
		||||
		m_client = client;
 | 
			
		||||
		m_formname.clear();
 | 
			
		||||
	}
 | 
			
		||||
	TextDestPlayerInventory(Client *client, const std::string &formname)
 | 
			
		||||
	{
 | 
			
		||||
		m_client = client;
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		m_client->sendInventoryFields(m_formname, fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct LocalFormspecHandler : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	LocalFormspecHandler(const std::string &formname)
 | 
			
		||||
	{
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LocalFormspecHandler(const std::string &formname, Client *client):
 | 
			
		||||
		m_client(client)
 | 
			
		||||
	{
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_formname == "MT_PAUSE_MENU") {
 | 
			
		||||
			if (fields.find("btn_sound") != fields.end()) {
 | 
			
		||||
				g_gamecallback->changeVolume();
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (fields.find("btn_key_config") != fields.end()) {
 | 
			
		||||
				g_gamecallback->keyConfig();
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (fields.find("btn_touchscreen_layout") != fields.end()) {
 | 
			
		||||
				g_gamecallback->touchscreenLayout();
 | 
			
		||||
				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();
 | 
			
		||||
#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();
 | 
			
		||||
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_client->modsLoaded())
 | 
			
		||||
			m_client->getScript()->on_formspec_input(m_formname, fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Form update callback */
 | 
			
		||||
 | 
			
		||||
class NodeMetadataFormSource: public IFormSource
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	NodeMetadataFormSource(ClientMap *map, v3s16 p):
 | 
			
		||||
		m_map(map),
 | 
			
		||||
		m_p(p)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	const std::string &getForm() const
 | 
			
		||||
	{
 | 
			
		||||
		static const std::string empty_string = "";
 | 
			
		||||
		NodeMetadata *meta = m_map->getNodeMetadata(m_p);
 | 
			
		||||
 | 
			
		||||
		if (!meta)
 | 
			
		||||
			return empty_string;
 | 
			
		||||
 | 
			
		||||
		return meta->getString("formspec");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual std::string resolveText(const std::string &str)
 | 
			
		||||
	{
 | 
			
		||||
		NodeMetadata *meta = m_map->getNodeMetadata(m_p);
 | 
			
		||||
 | 
			
		||||
		if (!meta)
 | 
			
		||||
			return str;
 | 
			
		||||
 | 
			
		||||
		return meta->resolveString(str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ClientMap *m_map;
 | 
			
		||||
	v3s16 m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class PlayerInventoryFormSource: public IFormSource
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	PlayerInventoryFormSource(Client *client):
 | 
			
		||||
		m_client(client)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::string &getForm() const
 | 
			
		||||
	{
 | 
			
		||||
		LocalPlayer *player = m_client->getEnv().getLocalPlayer();
 | 
			
		||||
		return player->inventory_formspec;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class NodeDugEvent : public MtEvent
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
@@ -596,8 +422,6 @@ public:
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define SIZE_TAG "size[11,5.5,true]" // Fixed size (ignored in touchscreen mode)
 | 
			
		||||
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
 ****************************************************************************/
 | 
			
		||||
 | 
			
		||||
@@ -699,7 +523,6 @@ protected:
 | 
			
		||||
 | 
			
		||||
	void updateInteractTimers(f32 dtime);
 | 
			
		||||
	bool checkConnection();
 | 
			
		||||
	bool handleCallbacks();
 | 
			
		||||
	void processQueues();
 | 
			
		||||
	void updateProfilers(const RunStats &stats, const FpsControl &draw_times, f32 dtime);
 | 
			
		||||
	void updateDebugState();
 | 
			
		||||
@@ -713,7 +536,6 @@ protected:
 | 
			
		||||
	bool shouldShowTouchControls();
 | 
			
		||||
 | 
			
		||||
	void dropSelectedItem(bool single_item = false);
 | 
			
		||||
	void openInventory();
 | 
			
		||||
	void openConsole(float scale, const wchar_t *line=NULL);
 | 
			
		||||
	void toggleFreeMove();
 | 
			
		||||
	void toggleFreeMoveAlt();
 | 
			
		||||
@@ -815,9 +637,6 @@ private:
 | 
			
		||||
		bool disable_camera_update = false;
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	void showDeathFormspecLegacy();
 | 
			
		||||
	void showPauseMenu();
 | 
			
		||||
 | 
			
		||||
	void pauseAnimation();
 | 
			
		||||
	void resumeAnimation();
 | 
			
		||||
 | 
			
		||||
@@ -882,6 +701,7 @@ private:
 | 
			
		||||
	irr_ptr<Sky> sky;
 | 
			
		||||
	Hud *hud = nullptr;
 | 
			
		||||
	Minimap *mapper = nullptr;
 | 
			
		||||
	GameFormSpec m_game_formspec;
 | 
			
		||||
 | 
			
		||||
	// Map server hud ids to client hud ids
 | 
			
		||||
	std::unordered_map<u32, u32> m_hud_server_to_client;
 | 
			
		||||
@@ -1089,6 +909,8 @@ bool Game::startup(bool *kill,
 | 
			
		||||
 | 
			
		||||
	m_rendering_engine->initialize(client, hud);
 | 
			
		||||
 | 
			
		||||
	m_game_formspec.init(client, m_rendering_engine, input);
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -1159,7 +981,7 @@ void Game::run()
 | 
			
		||||
 | 
			
		||||
		if (!checkConnection())
 | 
			
		||||
			break;
 | 
			
		||||
		if (!handleCallbacks())
 | 
			
		||||
		if (!m_game_formspec.handleCallbacks())
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		processQueues();
 | 
			
		||||
@@ -1191,7 +1013,7 @@ void Game::run()
 | 
			
		||||
		updateProfilerGraphs(&graph);
 | 
			
		||||
 | 
			
		||||
		if (m_does_lost_focus_pause_game && !device->isWindowFocused() && !isMenuActive()) {
 | 
			
		||||
			showPauseMenu();
 | 
			
		||||
			m_game_formspec.showPauseMenu();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -1203,10 +1025,6 @@ void Game::run()
 | 
			
		||||
 | 
			
		||||
void Game::shutdown()
 | 
			
		||||
{
 | 
			
		||||
	auto formspec = m_game_ui->getFormspecGUI();
 | 
			
		||||
	if (formspec)
 | 
			
		||||
		formspec->quitMenu();
 | 
			
		||||
 | 
			
		||||
	// Clear text when exiting.
 | 
			
		||||
	m_game_ui->clearText();
 | 
			
		||||
 | 
			
		||||
@@ -1228,8 +1046,6 @@ void Game::shutdown()
 | 
			
		||||
		g_menumgr.deleteFront();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_game_ui->deleteFormspec();
 | 
			
		||||
 | 
			
		||||
	chat_backend->addMessage(L"", L"# Disconnected.");
 | 
			
		||||
	chat_backend->addMessage(L"", L"");
 | 
			
		||||
 | 
			
		||||
@@ -1822,55 +1638,6 @@ inline bool Game::checkConnection()
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* returns false if game should exit, otherwise true
 | 
			
		||||
 */
 | 
			
		||||
inline bool Game::handleCallbacks()
 | 
			
		||||
{
 | 
			
		||||
	if (g_gamecallback->disconnect_requested) {
 | 
			
		||||
		g_gamecallback->disconnect_requested = false;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->changepassword_requested) {
 | 
			
		||||
		(void)make_irr<GUIPasswordChange>(guienv, guiroot, -1,
 | 
			
		||||
				       &g_menumgr, client, texture_src);
 | 
			
		||||
		g_gamecallback->changepassword_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->changevolume_requested) {
 | 
			
		||||
		(void)make_irr<GUIVolumeChange>(guienv, guiroot, -1,
 | 
			
		||||
				     &g_menumgr, texture_src);
 | 
			
		||||
		g_gamecallback->changevolume_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->keyconfig_requested) {
 | 
			
		||||
		(void)make_irr<GUIKeyChangeMenu>(guienv, guiroot, -1,
 | 
			
		||||
				      &g_menumgr, texture_src);
 | 
			
		||||
		g_gamecallback->keyconfig_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->touchscreenlayout_requested) {
 | 
			
		||||
		(new GUITouchscreenLayout(guienv, guiroot, -1,
 | 
			
		||||
				     &g_menumgr, texture_src))->drop();
 | 
			
		||||
		g_gamecallback->touchscreenlayout_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!g_gamecallback->show_open_url_dialog.empty()) {
 | 
			
		||||
		(void)make_irr<GUIOpenURLMenu>(guienv, guiroot, -1,
 | 
			
		||||
				 &g_menumgr, texture_src, g_gamecallback->show_open_url_dialog);
 | 
			
		||||
		g_gamecallback->show_open_url_dialog.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->keyconfig_changed) {
 | 
			
		||||
		input->keycache.populate(); // update the cache with new settings
 | 
			
		||||
		g_gamecallback->keyconfig_changed = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Game::processQueues()
 | 
			
		||||
{
 | 
			
		||||
	texture_src->processQueue();
 | 
			
		||||
@@ -1897,10 +1664,7 @@ void Game::updateDebugState()
 | 
			
		||||
	if (!has_debug) {
 | 
			
		||||
		draw_control->show_wireframe = false;
 | 
			
		||||
		m_flags.disable_camera_update = false;
 | 
			
		||||
		auto formspec = m_game_ui->getFormspecGUI();
 | 
			
		||||
		if (formspec) {
 | 
			
		||||
			formspec->setDebugView(false);
 | 
			
		||||
		}
 | 
			
		||||
		m_game_formspec.disableDebugView();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// noclip
 | 
			
		||||
@@ -2044,10 +1808,7 @@ void Game::processUserInput(f32 dtime)
 | 
			
		||||
	input->step(dtime);
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
	auto formspec = m_game_ui->getFormspecGUI();
 | 
			
		||||
	if (formspec)
 | 
			
		||||
		formspec->getAndroidUIInput();
 | 
			
		||||
	else
 | 
			
		||||
	if (!m_game_formspec.handleAndroidUIInput())
 | 
			
		||||
		handleAndroidChatInput();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@@ -2072,13 +1833,13 @@ void Game::processKeyInput()
 | 
			
		||||
		if (g_settings->getBool("continuous_forward"))
 | 
			
		||||
			toggleAutoforward();
 | 
			
		||||
	} else if (wasKeyDown(KeyType::INVENTORY)) {
 | 
			
		||||
		openInventory();
 | 
			
		||||
		m_game_formspec.showPlayerInventory();
 | 
			
		||||
	} else if (input->cancelPressed()) {
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
		m_android_chat_open = false;
 | 
			
		||||
#endif
 | 
			
		||||
		if (!gui_chat_console->isOpenInhibited()) {
 | 
			
		||||
			showPauseMenu();
 | 
			
		||||
			m_game_formspec.showPauseMenu();
 | 
			
		||||
		}
 | 
			
		||||
	} else if (wasKeyDown(KeyType::CHAT)) {
 | 
			
		||||
		openConsole(0.2, L"");
 | 
			
		||||
@@ -2246,45 +2007,6 @@ void Game::dropSelectedItem(bool single_item)
 | 
			
		||||
	client->inventoryAction(a);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Game::openInventory()
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't permit to open inventory is CAO or player doesn't exists.
 | 
			
		||||
	 * This prevent showing an empty inventory at player load
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	LocalPlayer *player = client->getEnv().getLocalPlayer();
 | 
			
		||||
	if (!player || !player->getCAO())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	infostream << "Game: Launching inventory" << std::endl;
 | 
			
		||||
 | 
			
		||||
	PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(client);
 | 
			
		||||
 | 
			
		||||
	InventoryLocation inventoryloc;
 | 
			
		||||
	inventoryloc.setCurrentPlayer();
 | 
			
		||||
 | 
			
		||||
	if (client->modsLoaded() && client->getScript()->on_inventory_open(fs_src->m_client->getInventory(inventoryloc))) {
 | 
			
		||||
		delete fs_src;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fs_src->getForm().empty()) {
 | 
			
		||||
		delete fs_src;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TextDest *txt_dst = new TextDestPlayerInventory(client);
 | 
			
		||||
	auto *&formspec = m_game_ui->updateFormspec("");
 | 
			
		||||
	GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
 | 
			
		||||
		&input->joystick, fs_src, txt_dst, client->getFormspecPrepend(),
 | 
			
		||||
		sound_manager.get());
 | 
			
		||||
 | 
			
		||||
	formspec->setFormSpec(fs_src->getForm(), inventoryloc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void Game::openConsole(float scale, const wchar_t *line)
 | 
			
		||||
{
 | 
			
		||||
	assert(scale > 0.0f && scale <= 1.0f);
 | 
			
		||||
@@ -2886,28 +2608,13 @@ void Game::handleClientEvent_PlayerForceMove(ClientEvent *event, CameraOrientati
 | 
			
		||||
 | 
			
		||||
void Game::handleClientEvent_DeathscreenLegacy(ClientEvent *event, CameraOrientation *cam)
 | 
			
		||||
{
 | 
			
		||||
	showDeathFormspecLegacy();
 | 
			
		||||
	m_game_formspec.showDeathFormspecLegacy();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation *cam)
 | 
			
		||||
{
 | 
			
		||||
	if (event->show_formspec.formspec->empty()) {
 | 
			
		||||
		auto formspec = m_game_ui->getFormspecGUI();
 | 
			
		||||
		if (formspec && (event->show_formspec.formname->empty()
 | 
			
		||||
				|| *(event->show_formspec.formname) == m_game_ui->getFormspecName())) {
 | 
			
		||||
			formspec->quitMenu();
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		FormspecFormSource *fs_src =
 | 
			
		||||
			new FormspecFormSource(*(event->show_formspec.formspec));
 | 
			
		||||
		TextDestPlayerInventory *txt_dst =
 | 
			
		||||
			new TextDestPlayerInventory(client, *(event->show_formspec.formname));
 | 
			
		||||
 | 
			
		||||
		auto *&formspec = m_game_ui->updateFormspec(*(event->show_formspec.formname));
 | 
			
		||||
		GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
 | 
			
		||||
			&input->joystick, fs_src, txt_dst, client->getFormspecPrepend(),
 | 
			
		||||
			sound_manager.get());
 | 
			
		||||
	}
 | 
			
		||||
	m_game_formspec.showFormSpec(*event->show_formspec.formspec,
 | 
			
		||||
		*event->show_formspec.formname);
 | 
			
		||||
 | 
			
		||||
	delete event->show_formspec.formspec;
 | 
			
		||||
	delete event->show_formspec.formname;
 | 
			
		||||
@@ -2915,11 +2622,8 @@ void Game::handleClientEvent_ShowFormSpec(ClientEvent *event, CameraOrientation
 | 
			
		||||
 | 
			
		||||
void Game::handleClientEvent_ShowLocalFormSpec(ClientEvent *event, CameraOrientation *cam)
 | 
			
		||||
{
 | 
			
		||||
	FormspecFormSource *fs_src = new FormspecFormSource(*event->show_formspec.formspec);
 | 
			
		||||
	LocalFormspecHandler *txt_dst =
 | 
			
		||||
		new LocalFormspecHandler(*event->show_formspec.formname, client);
 | 
			
		||||
	GUIFormSpecMenu::create(m_game_ui->getFormspecGUI(), client, m_rendering_engine->get_gui_env(),
 | 
			
		||||
			&input->joystick, fs_src, txt_dst, client->getFormspecPrepend(), sound_manager.get());
 | 
			
		||||
	m_game_formspec.showLocalFormSpec(*event->show_formspec.formspec,
 | 
			
		||||
		*event->show_formspec.formname);
 | 
			
		||||
 | 
			
		||||
	delete event->show_formspec.formspec;
 | 
			
		||||
	delete event->show_formspec.formname;
 | 
			
		||||
@@ -3657,21 +3361,7 @@ bool Game::nodePlacement(const ItemDefinition &selected_def,
 | 
			
		||||
		if (nodedef_manager->get(map.getNode(nodepos)).rightclickable)
 | 
			
		||||
			client->interact(INTERACT_PLACE, pointed);
 | 
			
		||||
 | 
			
		||||
		infostream << "Launching custom inventory view" << std::endl;
 | 
			
		||||
 | 
			
		||||
		InventoryLocation inventoryloc;
 | 
			
		||||
		inventoryloc.setNodeMeta(nodepos);
 | 
			
		||||
 | 
			
		||||
		NodeMetadataFormSource *fs_src = new NodeMetadataFormSource(
 | 
			
		||||
			&client->getEnv().getClientMap(), nodepos);
 | 
			
		||||
		TextDest *txt_dst = new TextDestNodeMetadata(nodepos, client);
 | 
			
		||||
 | 
			
		||||
		auto *&formspec = m_game_ui->updateFormspec("");
 | 
			
		||||
		GUIFormSpecMenu::create(formspec, client, m_rendering_engine->get_gui_env(),
 | 
			
		||||
			&input->joystick, fs_src, txt_dst, client->getFormspecPrepend(),
 | 
			
		||||
			sound_manager.get());
 | 
			
		||||
 | 
			
		||||
		formspec->setFormSpec(meta->getString("formspec"), inventoryloc);
 | 
			
		||||
		m_game_formspec.showNodeFormspec(meta->getString("formspec"), nodepos);
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
@@ -4207,34 +3897,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime,
 | 
			
		||||
	m_game_ui->update(*stats, client, draw_control, cam, runData.pointed_old,
 | 
			
		||||
			gui_chat_console.get(), dtime);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	   make sure menu is on top
 | 
			
		||||
	   1. Delete formspec menu reference if menu was removed
 | 
			
		||||
	   2. Else, make sure formspec menu is on top
 | 
			
		||||
	*/
 | 
			
		||||
	auto formspec = m_game_ui->getFormspecGUI();
 | 
			
		||||
	do { // breakable. only runs for one iteration
 | 
			
		||||
		if (!formspec)
 | 
			
		||||
			break;
 | 
			
		||||
 | 
			
		||||
		if (formspec->getReferenceCount() == 1) {
 | 
			
		||||
			// See GUIFormSpecMenu::create what refcnt = 1 means
 | 
			
		||||
			m_game_ui->deleteFormspec();
 | 
			
		||||
			break;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto &loc = formspec->getFormspecLocation();
 | 
			
		||||
		if (loc.type == InventoryLocation::NODEMETA) {
 | 
			
		||||
			NodeMetadata *meta = client->getEnv().getClientMap().getNodeMetadata(loc.p);
 | 
			
		||||
			if (!meta || meta->getString("formspec").empty()) {
 | 
			
		||||
				formspec->quitMenu();
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (isMenuActive())
 | 
			
		||||
			guiroot->bringToFront(formspec);
 | 
			
		||||
	} while (false);
 | 
			
		||||
	m_game_formspec.update();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
		==================== Drawing begins ====================
 | 
			
		||||
@@ -4451,145 +4114,6 @@ void Game::readSettings()
 | 
			
		||||
	m_does_lost_focus_pause_game = g_settings->getBool("pause_on_lost_focus");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
 Shutdown / cleanup
 | 
			
		||||
 ****************************************************************************/
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
 | 
			
		||||
void Game::showDeathFormspecLegacy()
 | 
			
		||||
{
 | 
			
		||||
	static std::string formspec_str =
 | 
			
		||||
		std::string("formspec_version[1]") +
 | 
			
		||||
		SIZE_TAG
 | 
			
		||||
		"bgcolor[#320000b4;true]"
 | 
			
		||||
		"label[4.85,1.35;" + gettext("You died") + "]"
 | 
			
		||||
		"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	/* Create menu */
 | 
			
		||||
	/* Note: FormspecFormSource and LocalFormspecHandler  *
 | 
			
		||||
	 * are deleted by guiFormSpecMenu                     */
 | 
			
		||||
	FormspecFormSource *fs_src = new FormspecFormSource(formspec_str);
 | 
			
		||||
	LocalFormspecHandler *txt_dst = new LocalFormspecHandler("MT_DEATH_SCREEN", client);
 | 
			
		||||
 | 
			
		||||
	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_respawn");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define GET_KEY_NAME(KEY) gettext(getKeySetting(#KEY).name())
 | 
			
		||||
void Game::showPauseMenu()
 | 
			
		||||
{
 | 
			
		||||
	std::string control_text;
 | 
			
		||||
 | 
			
		||||
	if (g_touchcontrols) {
 | 
			
		||||
		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,0.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
 | 
			
		||||
#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;"
 | 
			
		||||
		<< 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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/****************************************************************************/
 | 
			
		||||
/****************************************************************************
 | 
			
		||||
 extern function for launching the game
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										524
									
								
								src/client/game_formspec.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										524
									
								
								src/client/game_formspec.cpp
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,524 @@
 | 
			
		||||
// Luanti
 | 
			
		||||
// SPDX-License-Identifier: LGPL-2.1-or-later
 | 
			
		||||
// Copyright (C) 2010-2013 celeron55, Perttu Ahola <celeron55@gmail.com>
 | 
			
		||||
 | 
			
		||||
#include "game_formspec.h"
 | 
			
		||||
 | 
			
		||||
#include "gettext.h"
 | 
			
		||||
#include "nodemetadata.h"
 | 
			
		||||
#include "renderingengine.h"
 | 
			
		||||
#include "client.h"
 | 
			
		||||
#include "scripting_client.h"
 | 
			
		||||
#include "clientmap.h"
 | 
			
		||||
#include "gui/guiFormSpecMenu.h"
 | 
			
		||||
#include "gui/mainmenumanager.h"
 | 
			
		||||
#include "gui/touchcontrols.h"
 | 
			
		||||
#include "gui/touchscreeneditor.h"
 | 
			
		||||
#include "gui/guiPasswordChange.h"
 | 
			
		||||
#include "gui/guiKeyChangeMenu.h"
 | 
			
		||||
#include "gui/guiPasswordChange.h"
 | 
			
		||||
#include "gui/guiOpenURL.h"
 | 
			
		||||
#include "gui/guiVolumeChange.h"
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
	Text input system
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
struct TextDestNodeMetadata : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	TextDestNodeMetadata(v3s16 p, Client *client)
 | 
			
		||||
	{
 | 
			
		||||
		m_p = p;
 | 
			
		||||
		m_client = client;
 | 
			
		||||
	}
 | 
			
		||||
	// This is deprecated I guess? -celeron55
 | 
			
		||||
	void gotText(const std::wstring &text)
 | 
			
		||||
	{
 | 
			
		||||
		std::string ntext = wide_to_utf8(text);
 | 
			
		||||
		infostream << "Submitting 'text' field of node at (" << m_p.X << ","
 | 
			
		||||
			   << m_p.Y << "," << m_p.Z << "): " << ntext << std::endl;
 | 
			
		||||
		StringMap fields;
 | 
			
		||||
		fields["text"] = ntext;
 | 
			
		||||
		m_client->sendNodemetaFields(m_p, "", fields);
 | 
			
		||||
	}
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		m_client->sendNodemetaFields(m_p, "", fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	v3s16 m_p;
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct TextDestPlayerInventory : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	TextDestPlayerInventory(Client *client)
 | 
			
		||||
	{
 | 
			
		||||
		m_client = client;
 | 
			
		||||
		m_formname.clear();
 | 
			
		||||
	}
 | 
			
		||||
	TextDestPlayerInventory(Client *client, const std::string &formname)
 | 
			
		||||
	{
 | 
			
		||||
		m_client = client;
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		m_client->sendInventoryFields(m_formname, fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct LocalFormspecHandler : public TextDest
 | 
			
		||||
{
 | 
			
		||||
	LocalFormspecHandler(const std::string &formname)
 | 
			
		||||
	{
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LocalFormspecHandler(const std::string &formname, Client *client):
 | 
			
		||||
		m_client(client)
 | 
			
		||||
	{
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void gotText(const StringMap &fields)
 | 
			
		||||
	{
 | 
			
		||||
		if (m_formname == "MT_PAUSE_MENU") {
 | 
			
		||||
			if (fields.find("btn_sound") != fields.end()) {
 | 
			
		||||
				g_gamecallback->changeVolume();
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (fields.find("btn_key_config") != fields.end()) {
 | 
			
		||||
				g_gamecallback->keyConfig();
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			if (fields.find("btn_touchscreen_layout") != fields.end()) {
 | 
			
		||||
				g_gamecallback->touchscreenLayout();
 | 
			
		||||
				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();
 | 
			
		||||
#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();
 | 
			
		||||
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (m_client->modsLoaded())
 | 
			
		||||
			m_client->getScript()->on_formspec_input(m_formname, fields);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/* Form update callback */
 | 
			
		||||
 | 
			
		||||
class NodeMetadataFormSource: public IFormSource
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	NodeMetadataFormSource(ClientMap *map, v3s16 p):
 | 
			
		||||
		m_map(map),
 | 
			
		||||
		m_p(p)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
	const std::string &getForm() const
 | 
			
		||||
	{
 | 
			
		||||
		static const std::string empty_string = "";
 | 
			
		||||
		NodeMetadata *meta = m_map->getNodeMetadata(m_p);
 | 
			
		||||
 | 
			
		||||
		if (!meta)
 | 
			
		||||
			return empty_string;
 | 
			
		||||
 | 
			
		||||
		return meta->getString("formspec");
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	virtual std::string resolveText(const std::string &str)
 | 
			
		||||
	{
 | 
			
		||||
		NodeMetadata *meta = m_map->getNodeMetadata(m_p);
 | 
			
		||||
 | 
			
		||||
		if (!meta)
 | 
			
		||||
			return str;
 | 
			
		||||
 | 
			
		||||
		return meta->resolveString(str);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ClientMap *m_map;
 | 
			
		||||
	v3s16 m_p;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class PlayerInventoryFormSource: public IFormSource
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
	PlayerInventoryFormSource(Client *client):
 | 
			
		||||
		m_client(client)
 | 
			
		||||
	{
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::string &getForm() const
 | 
			
		||||
	{
 | 
			
		||||
		LocalPlayer *player = m_client->getEnv().getLocalPlayer();
 | 
			
		||||
		return player->inventory_formspec;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
//// GameFormSpec
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::deleteFormspec()
 | 
			
		||||
{
 | 
			
		||||
	if (m_formspec) {
 | 
			
		||||
		m_formspec->drop();
 | 
			
		||||
		m_formspec = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
	m_formname.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
GameFormSpec::~GameFormSpec() {
 | 
			
		||||
	if (m_formspec)
 | 
			
		||||
		m_formspec->quitMenu();
 | 
			
		||||
	this->deleteFormspec();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::showFormSpec(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());
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::showLocalFormSpec(const std::string &formspec, const std::string &formname)
 | 
			
		||||
{
 | 
			
		||||
	FormspecFormSource *fs_src = new FormspecFormSource(formspec);
 | 
			
		||||
	LocalFormspecHandler *txt_dst =
 | 
			
		||||
		new LocalFormspecHandler(formname, m_client);
 | 
			
		||||
	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::showNodeFormspec(const std::string &formspec, const v3s16 &nodepos)
 | 
			
		||||
{
 | 
			
		||||
	infostream << "Launching custom inventory view" << std::endl;
 | 
			
		||||
 | 
			
		||||
	InventoryLocation inventoryloc;
 | 
			
		||||
	inventoryloc.setNodeMeta(nodepos);
 | 
			
		||||
 | 
			
		||||
	NodeMetadataFormSource *fs_src = new NodeMetadataFormSource(
 | 
			
		||||
		&m_client->getEnv().getClientMap(), nodepos);
 | 
			
		||||
	TextDest *txt_dst = new TextDestNodeMetadata(nodepos, m_client);
 | 
			
		||||
 | 
			
		||||
	m_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());
 | 
			
		||||
 | 
			
		||||
	m_formspec->setFormSpec(formspec, inventoryloc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::showPlayerInventory()
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	 * Don't permit to open inventory is CAO or player doesn't exists.
 | 
			
		||||
	 * This prevent showing an empty inventory at player load
 | 
			
		||||
	 */
 | 
			
		||||
 | 
			
		||||
	LocalPlayer *player = m_client->getEnv().getLocalPlayer();
 | 
			
		||||
	if (!player || !player->getCAO())
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	infostream << "Game: Launching inventory" << std::endl;
 | 
			
		||||
 | 
			
		||||
	PlayerInventoryFormSource *fs_src = new PlayerInventoryFormSource(m_client);
 | 
			
		||||
 | 
			
		||||
	InventoryLocation inventoryloc;
 | 
			
		||||
	inventoryloc.setCurrentPlayer();
 | 
			
		||||
 | 
			
		||||
	if (m_client->modsLoaded() && m_client->getScript()->on_inventory_open(m_client->getInventory(inventoryloc))) {
 | 
			
		||||
		delete fs_src;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (fs_src->getForm().empty()) {
 | 
			
		||||
		delete fs_src;
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	TextDest *txt_dst = new TextDestPlayerInventory(m_client);
 | 
			
		||||
	m_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());
 | 
			
		||||
 | 
			
		||||
	m_formspec->setFormSpec(fs_src->getForm(), inventoryloc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define SIZE_TAG "size[11,5.5,true]" // Fixed size (ignored in touchscreen mode)
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::showPauseMenu()
 | 
			
		||||
{
 | 
			
		||||
	std::string control_text;
 | 
			
		||||
 | 
			
		||||
	if (g_touchcontrols) {
 | 
			
		||||
		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"
 | 
			
		||||
			);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto simple_singleplayer_mode = m_client->m_simple_singleplayer_mode;
 | 
			
		||||
 | 
			
		||||
	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,0.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
 | 
			
		||||
#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;"
 | 
			
		||||
		<< 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 = m_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");
 | 
			
		||||
 | 
			
		||||
	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)
 | 
			
		||||
	m_formspec->doPause = true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::showDeathFormspecLegacy()
 | 
			
		||||
{
 | 
			
		||||
	static std::string formspec_str =
 | 
			
		||||
		std::string("formspec_version[1]") +
 | 
			
		||||
		SIZE_TAG
 | 
			
		||||
		"bgcolor[#320000b4;true]"
 | 
			
		||||
		"label[4.85,1.35;" + gettext("You died") + "]"
 | 
			
		||||
		"button_exit[4,3;3,0.5;btn_respawn;" + gettext("Respawn") + "]"
 | 
			
		||||
		;
 | 
			
		||||
 | 
			
		||||
	/* Create menu */
 | 
			
		||||
	/* 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);
 | 
			
		||||
 | 
			
		||||
	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_respawn");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::update()
 | 
			
		||||
{
 | 
			
		||||
	/*
 | 
			
		||||
	   make sure menu is on top
 | 
			
		||||
	   1. Delete formspec menu reference if menu was removed
 | 
			
		||||
	   2. Else, make sure formspec menu is on top
 | 
			
		||||
	*/
 | 
			
		||||
	if (!m_formspec)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	if (m_formspec->getReferenceCount() == 1) {
 | 
			
		||||
		// See GUIFormSpecMenu::create what refcnt = 1 means
 | 
			
		||||
		this->deleteFormspec();
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto &loc = m_formspec->getFormspecLocation();
 | 
			
		||||
	if (loc.type == InventoryLocation::NODEMETA) {
 | 
			
		||||
		NodeMetadata *meta = m_client->getEnv().getClientMap().getNodeMetadata(loc.p);
 | 
			
		||||
		if (!meta || meta->getString("formspec").empty()) {
 | 
			
		||||
			m_formspec->quitMenu();
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (isMenuActive())
 | 
			
		||||
		guiroot->bringToFront(m_formspec);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameFormSpec::disableDebugView()
 | 
			
		||||
{
 | 
			
		||||
	if (m_formspec) {
 | 
			
		||||
		m_formspec->setDebugView(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* returns false if game should exit, otherwise true
 | 
			
		||||
 */
 | 
			
		||||
bool GameFormSpec::handleCallbacks()
 | 
			
		||||
{
 | 
			
		||||
	auto texture_src = m_client->getTextureSource();
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->disconnect_requested) {
 | 
			
		||||
		g_gamecallback->disconnect_requested = false;
 | 
			
		||||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->changepassword_requested) {
 | 
			
		||||
		(void)make_irr<GUIPasswordChange>(guienv, guiroot, -1,
 | 
			
		||||
				       &g_menumgr, m_client, texture_src);
 | 
			
		||||
		g_gamecallback->changepassword_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->changevolume_requested) {
 | 
			
		||||
		(void)make_irr<GUIVolumeChange>(guienv, guiroot, -1,
 | 
			
		||||
				     &g_menumgr, texture_src);
 | 
			
		||||
		g_gamecallback->changevolume_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->keyconfig_requested) {
 | 
			
		||||
		(void)make_irr<GUIKeyChangeMenu>(guienv, guiroot, -1,
 | 
			
		||||
				      &g_menumgr, texture_src);
 | 
			
		||||
		g_gamecallback->keyconfig_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->touchscreenlayout_requested) {
 | 
			
		||||
		(new GUITouchscreenLayout(guienv, guiroot, -1,
 | 
			
		||||
				     &g_menumgr, texture_src))->drop();
 | 
			
		||||
		g_gamecallback->touchscreenlayout_requested = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!g_gamecallback->show_open_url_dialog.empty()) {
 | 
			
		||||
		(void)make_irr<GUIOpenURLMenu>(guienv, guiroot, -1,
 | 
			
		||||
				 &g_menumgr, texture_src, g_gamecallback->show_open_url_dialog);
 | 
			
		||||
		g_gamecallback->show_open_url_dialog.clear();
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (g_gamecallback->keyconfig_changed) {
 | 
			
		||||
		m_input->keycache.populate(); // update the cache with new settings
 | 
			
		||||
		g_gamecallback->keyconfig_changed = false;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
bool GameFormSpec::handleAndroidUIInput()
 | 
			
		||||
{
 | 
			
		||||
	if (m_formspec) {
 | 
			
		||||
		m_formspec->getAndroidUIInput();
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	return false;
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										62
									
								
								src/client/game_formspec.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/client/game_formspec.h
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,62 @@
 | 
			
		||||
// Luanti
 | 
			
		||||
// SPDX-License-Identifier: LGPL-2.1-or-later
 | 
			
		||||
// Copyright (C) 2024 cx384
 | 
			
		||||
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include <string>
 | 
			
		||||
#include "irr_v3d.h"
 | 
			
		||||
 | 
			
		||||
class Client;
 | 
			
		||||
class RenderingEngine;
 | 
			
		||||
class InputHandler;
 | 
			
		||||
class ISoundManager;
 | 
			
		||||
class GUIFormSpecMenu;
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
This object intend to contain the core fromspec functionality.
 | 
			
		||||
It includes:
 | 
			
		||||
  - methods to show specific formspec menus
 | 
			
		||||
  - storing the opened fromspec
 | 
			
		||||
  - handling fromspec related callbacks
 | 
			
		||||
 */
 | 
			
		||||
struct GameFormSpec
 | 
			
		||||
{
 | 
			
		||||
	void init(Client *client, RenderingEngine *rendering_engine, InputHandler *input)
 | 
			
		||||
	{
 | 
			
		||||
		m_client = client;
 | 
			
		||||
		m_rendering_engine = rendering_engine;
 | 
			
		||||
		m_input = input;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	~GameFormSpec();
 | 
			
		||||
 | 
			
		||||
	void showFormSpec(const std::string &formspec, const std::string &formname);
 | 
			
		||||
	void showLocalFormSpec(const std::string &formspec, const std::string &formname);
 | 
			
		||||
	void showNodeFormspec(const std::string &formspec, const v3s16 &nodepos);
 | 
			
		||||
	void showPlayerInventory();
 | 
			
		||||
	void showDeathFormspecLegacy();
 | 
			
		||||
	void showPauseMenu();
 | 
			
		||||
 | 
			
		||||
	void update();
 | 
			
		||||
	void disableDebugView();
 | 
			
		||||
 | 
			
		||||
	bool handleCallbacks();
 | 
			
		||||
 | 
			
		||||
#ifdef __ANDROID__
 | 
			
		||||
	// Returns false if no formspec open
 | 
			
		||||
	bool handleAndroidUIInput();
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
	Client *m_client;
 | 
			
		||||
	RenderingEngine *m_rendering_engine;
 | 
			
		||||
	InputHandler *m_input;
 | 
			
		||||
 | 
			
		||||
	// Default: "". If other than "": Empty show_formspec packets will only
 | 
			
		||||
	// close the formspec when the formname matches
 | 
			
		||||
	std::string m_formname;
 | 
			
		||||
	GUIFormSpecMenu *m_formspec = nullptr;
 | 
			
		||||
 | 
			
		||||
	void deleteFormspec();
 | 
			
		||||
};
 | 
			
		||||
@@ -8,7 +8,6 @@
 | 
			
		||||
#include <gettext.h>
 | 
			
		||||
#include "gui/mainmenumanager.h"
 | 
			
		||||
#include "gui/guiChatConsole.h"
 | 
			
		||||
#include "gui/guiFormSpecMenu.h"
 | 
			
		||||
#include "gui/touchcontrols.h"
 | 
			
		||||
#include "util/enriched_string.h"
 | 
			
		||||
#include "util/pointedthing.h"
 | 
			
		||||
@@ -319,17 +318,6 @@ void GameUI::toggleProfiler()
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void GameUI::deleteFormspec()
 | 
			
		||||
{
 | 
			
		||||
	if (m_formspec) {
 | 
			
		||||
		m_formspec->drop();
 | 
			
		||||
		m_formspec = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	m_formname.clear();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GameUI::clearText()
 | 
			
		||||
{
 | 
			
		||||
	if (m_guitext_chat) {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,7 +13,6 @@ using namespace irr;
 | 
			
		||||
class Client;
 | 
			
		||||
class EnrichedString;
 | 
			
		||||
class GUIChatConsole;
 | 
			
		||||
class GUIFormSpecMenu;
 | 
			
		||||
struct MapDrawControl;
 | 
			
		||||
struct PointedThing;
 | 
			
		||||
 | 
			
		||||
@@ -79,15 +78,6 @@ public:
 | 
			
		||||
	void toggleHud();
 | 
			
		||||
	void toggleProfiler();
 | 
			
		||||
 | 
			
		||||
	GUIFormSpecMenu *&updateFormspec(const std::string &formname)
 | 
			
		||||
	{
 | 
			
		||||
		m_formname = formname;
 | 
			
		||||
		return m_formspec;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const std::string &getFormspecName() { return m_formname; }
 | 
			
		||||
	GUIFormSpecMenu *&getFormspecGUI() { return m_formspec; }
 | 
			
		||||
	void deleteFormspec();
 | 
			
		||||
	void clearText();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
@@ -113,9 +103,4 @@ private:
 | 
			
		||||
	gui::IGUIStaticText *m_guitext_profiler = nullptr; // Profiler text
 | 
			
		||||
	u8 m_profiler_current_page = 0;
 | 
			
		||||
	const u8 m_profiler_max_page = 3;
 | 
			
		||||
 | 
			
		||||
	// Default: "". If other than "": Empty show_formspec packets will only
 | 
			
		||||
	// close the formspec when the formname matches
 | 
			
		||||
	std::string m_formname;
 | 
			
		||||
	GUIFormSpecMenu *m_formspec = nullptr;
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user