From 321bcf5c4437e8ccc599be9004ad1590a6639c46 Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 10 Dec 2023 19:09:51 +0100 Subject: [PATCH 1/3] GUIFormspecMenu: Fix race condition between quit event and cleanup in Game (#14010) To not instantly free GUIFormSpec upon close/quit, Game periodically cleans up the remaining instance on the next frame. When a new formspec is received and processed after closing the previous formspec but before the cleanup in Game, the formspec would be closed regardless. This now re-creates the formspec when the old one is already pending for removal. --- src/client/game.cpp | 1 + src/gui/guiFormSpecMenu.cpp | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/client/game.cpp b/src/client/game.cpp index cc8891547..ea57f5085 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -4124,6 +4124,7 @@ void Game::updateFrame(ProfilerGraph *graph, RunStats *stats, f32 dtime, break; if (formspec->getReferenceCount() == 1) { + // See GUIFormSpecMenu::create what refcnt = 1 means m_game_ui->deleteFormspec(); break; } diff --git a/src/gui/guiFormSpecMenu.cpp b/src/gui/guiFormSpecMenu.cpp index ad1f30005..445c5b902 100644 --- a/src/gui/guiFormSpecMenu.cpp +++ b/src/gui/guiFormSpecMenu.cpp @@ -138,11 +138,23 @@ void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client, gui::IGUIEnvironment *guienv, JoystickController *joystick, IFormSource *fs_src, TextDest *txt_dest, const std::string &formspecPrepend, ISoundManager *sound_manager) { + if (cur_formspec && cur_formspec->getReferenceCount() == 1) { + /* + Why reference count == 1? Reason: + 1 on creation (see "drop()" remark below) + +1 for being a guiroot child + +1 when focused (CGUIEnvironment::setFocus) + + Hence re-create the formspec when it's existing without any parent. + */ + cur_formspec->drop(); + cur_formspec = nullptr; + } + if (cur_formspec == nullptr) { cur_formspec = new GUIFormSpecMenu(joystick, guiroot, -1, &g_menumgr, client, guienv, client->getTextureSource(), sound_manager, fs_src, txt_dest, formspecPrepend); - cur_formspec->doPause = false; /* Caution: do not call (*cur_formspec)->drop() here -- @@ -151,12 +163,13 @@ void GUIFormSpecMenu::create(GUIFormSpecMenu *&cur_formspec, Client *client, remaining reference (i.e. the menu was removed) and delete it in that case. */ - } else { cur_formspec->setFormspecPrepend(formspecPrepend); cur_formspec->setFormSource(fs_src); cur_formspec->setTextDest(txt_dest); } + + cur_formspec->doPause = false; } void GUIFormSpecMenu::removeTooltip() From 55fafb7d25fe5a127332e3e9f3e54e54ec1ec20c Mon Sep 17 00:00:00 2001 From: Muhammad Rifqi Priyo Susanto Date: Mon, 11 Dec 2023 01:11:39 +0700 Subject: [PATCH 2/3] Add sound volume when unfocused setting (#14083) This adds a new setting to set sound volume multiplier when Minetest window is unfocused/inactive (sound_volume_unfocused, located in Settings > Graphics and Audio > Audio > Volume when unfocused). If the window is not focused, the sound volume will be multiplied by sound_volume_unfocused setting. The sound volume will be set back to sound_volume again when the window is focused. --- builtin/settingtypes.txt | 3 +++ src/client/game.cpp | 14 +------------- src/client/sound.cpp | 24 ++++++++++++++++++++++++ src/client/sound.h | 6 ++++++ src/defaultsettings.cpp | 1 + src/gui/guiEngine.cpp | 4 +++- 6 files changed, 38 insertions(+), 14 deletions(-) diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index ee7ba72d2..ec71f1998 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -623,6 +623,9 @@ bloom_radius (Bloom Radius) float 1 0.1 8 # Requires the sound system to be enabled. sound_volume (Volume) float 0.8 0.0 1.0 +# Volume multiplier when the window is unfocused. +sound_volume_unfocused (Volume when unfocused) float 0.3 0.0 1.0 + # Whether to mute sounds. You can unmute sounds at any time, unless the # sound system is disabled (enable_sound=false). # In-game, you can toggle the mute state with the mute key or by using the diff --git a/src/client/game.cpp b/src/client/game.cpp index ea57f5085..7bc2c8697 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -3209,19 +3209,7 @@ void Game::updateSound(f32 dtime) camera->getDirection(), camera->getCameraNode()->getUpVector()); - bool mute_sound = g_settings->getBool("mute_sound"); - if (mute_sound) { - sound_manager->setListenerGain(0.0f); - } else { - // Check if volume is in the proper range, else fix it. - float old_volume = g_settings->getFloat("sound_volume"); - float new_volume = rangelim(old_volume, 0.0f, 1.0f); - sound_manager->setListenerGain(new_volume); - - if (old_volume != new_volume) { - g_settings->setFloat("sound_volume", new_volume); - } - } + sound_volume_control(sound_manager.get(), device->isWindowActive()); // Tell the sound maker whether to make footstep sounds soundmaker->makes_footstep_sound = player->makes_footstep_sound; diff --git a/src/client/sound.cpp b/src/client/sound.cpp index b4b073242..b2b035b4e 100644 --- a/src/client/sound.cpp +++ b/src/client/sound.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "filesys.h" #include "log.h" #include "porting.h" +#include "settings.h" #include "util/numeric.h" #include #include @@ -95,3 +96,26 @@ void ISoundManager::freeId(sound_handle_t id, u32 num_owners) else it->second -= num_owners; } + +void sound_volume_control(ISoundManager *sound_mgr, bool is_window_active) +{ + bool mute_sound = g_settings->getBool("mute_sound"); + if (mute_sound) { + sound_mgr->setListenerGain(0.0f); + } else { + // Check if volume is in the proper range, else fix it. + float old_volume = g_settings->getFloat("sound_volume"); + float new_volume = rangelim(old_volume, 0.0f, 1.0f); + + if (old_volume != new_volume) { + g_settings->setFloat("sound_volume", new_volume); + } + + if (!is_window_active) { + new_volume *= g_settings->getFloat("sound_volume_unfocused"); + new_volume = rangelim(new_volume, 0.0f, 1.0f); + } + + sound_mgr->setListenerGain(new_volume); + } +} diff --git a/src/client/sound.h b/src/client/sound.h index ad5dbf649..132da708e 100644 --- a/src/client/sound.h +++ b/src/client/sound.h @@ -184,3 +184,9 @@ public: void fadeSound(sound_handle_t sound, f32 step, f32 target_gain) override {} void updateSoundPosVel(sound_handle_t sound, const v3f &pos, const v3f &vel) override {} }; + +/** + * A helper function to control sound volume based on some values: sound volume + * settings, mute sound setting, and window activity. + */ +void sound_volume_control(ISoundManager *sound_mgr, bool is_window_active); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 8ca079357..a815f89ed 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -40,6 +40,7 @@ void set_default_settings() settings->setDefault("address", ""); settings->setDefault("enable_sound", "true"); settings->setDefault("sound_volume", "0.8"); + settings->setDefault("sound_volume_unfocused", "0.3"); settings->setDefault("mute_sound", "false"); settings->setDefault("enable_mesh_cache", "false"); settings->setDefault("mesh_generation_interval", "0"); diff --git a/src/gui/guiEngine.cpp b/src/gui/guiEngine.cpp index fd1121346..7bdc067ac 100644 --- a/src/gui/guiEngine.cpp +++ b/src/gui/guiEngine.cpp @@ -23,7 +23,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "client/renderingengine.h" #include "scripting_mainmenu.h" -#include "util/numeric.h" #include "config.h" #include "version.h" #include "porting.h" @@ -296,6 +295,7 @@ void GUIEngine::run() driver->endScene(); IrrlichtDevice *device = m_rendering_engine->get_raw_device(); + u32 frametime_min = 1000 / (device->isWindowFocused() ? g_settings->getFloat("fps_max") : g_settings->getFloat("fps_max_unfocused")); @@ -310,6 +310,8 @@ void GUIEngine::run() m_script->step(); + sound_volume_control(m_sound_manager.get(), device->isWindowActive()); + m_sound_manager->step(dtime); #ifdef __ANDROID__ From a98200bb4c1edb2c982577fb01b30075665ab488 Mon Sep 17 00:00:00 2001 From: lhofhansl Date: Sun, 10 Dec 2023 10:12:37 -0800 Subject: [PATCH 3/3] Avoid movement jitter (#13093) This allows the client and server to agree on the position of objects and attached players even when there is lag. --- src/client/client.cpp | 4 ++-- src/collision.cpp | 6 +++--- src/constants.h | 7 +++++++ src/server.cpp | 4 ++-- 4 files changed, 14 insertions(+), 7 deletions(-) diff --git a/src/client/client.cpp b/src/client/client.cpp index c17fa2ab9..a49578ae0 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -393,8 +393,8 @@ void Client::connect(Address address, bool is_local_server) void Client::step(float dtime) { // Limit a bit - if (dtime > 2.0) - dtime = 2.0; + if (dtime > DTIME_LIMIT) + dtime = DTIME_LIMIT; m_animation_time += dtime; if(m_animation_time > 60.0) diff --git a/src/collision.cpp b/src/collision.cpp index 0649b5ced..0814791ed 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -241,13 +241,13 @@ collisionMoveResult collisionMoveSimple(Environment *env, IGameDef *gamedef, /* Calculate new velocity */ - if (dtime > 0.5f) { + if (dtime > DTIME_LIMIT) { if (!time_notification_done) { time_notification_done = true; - infostream << "collisionMoveSimple: maximum step interval exceeded," + warningstream << "collisionMoveSimple: maximum step interval exceeded," " lost movement details!"< 2.0) - dtime = 2.0; + if (dtime > DTIME_LIMIT) + dtime = DTIME_LIMIT; { MutexAutoLock lock(m_step_dtime_mutex); m_step_dtime += dtime;