From 492499c48e4c3ac7856e0cd862e955231afc39f8 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sat, 21 May 2022 23:45:13 +0100 Subject: [PATCH] Add display info to minetest.get_player_information() Fixes #10632 --- doc/lua_api.txt | 15 +++++++++++++++ src/client/client.cpp | 11 +++++++++++ src/client/client.h | 2 ++ src/client/game.cpp | 30 ++++++++++++++++++++++++----- src/clientdynamicinfo.h | 19 ++++++++++++++++++ src/clientiface.h | 9 ++++++++- src/network/clientopcodes.cpp | 1 + src/network/networkprotocol.h | 10 +++++++++- src/network/serveropcodes.cpp | 1 + src/network/serverpackethandler.cpp | 15 +++++++++++++++ src/script/common/c_converter.cpp | 9 +++++++++ src/script/common/c_converter.h | 1 + src/script/lua_api/l_server.cpp | 24 +++++++++++++++++++++++ src/server.cpp | 2 ++ src/server.h | 3 +++ 15 files changed, 145 insertions(+), 7 deletions(-) create mode 100644 src/clientdynamicinfo.h diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 6046a5902a0eb..edea5f9c7d9cd 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -4713,6 +4713,21 @@ Utilities protocol_version = 32, -- protocol version used by client formspec_version = 2, -- supported formspec version lang_code = "fr" -- Language code used for translation + + -- Will only be present if the client sent this information (requires v5.6+) + -- + -- Note that none of these things are constant, they are likely to change during a client + -- connection as the player changes the window size and moves it between monitors + display = { + screen_size = { -- Current window size, not including any decorations (window bar, etc) + x = 1308, + y = 577, + }, + dpi = 96, -- Dots per inch + gui_scaling = 1, -- gui_scaling setting + hud_scaling = 1, -- hud_scaling setting + }, + -- the following keys can be missing if no stats have been collected yet min_rtt = 0.01, -- minimum round trip time max_rtt = 0.2, -- maximum round trip time diff --git a/src/client/client.cpp b/src/client/client.cpp index 8ab96b7d10bfc..1ab47ad4c6400 100644 --- a/src/client/client.cpp +++ b/src/client/client.cpp @@ -1369,6 +1369,17 @@ void Client::sendHaveMedia(const std::vector &tokens) Send(&pkt); } +void Client::sendUpdateClientInfo(const ClientDynamicInfo& info) +{ + NetworkPacket pkt(TOSERVER_UPDATE_CLIENT_INFO, 4*2 + 2 + 4 + 4); + pkt << (u32)info.screen_size.X << (u32)info.screen_size.Y; + pkt << info.dpi; + pkt << info.gui_scaling; + pkt << info.hud_scaling; + + Send(&pkt); +} + void Client::removeNode(v3s16 p) { std::map modified_blocks; diff --git a/src/client/client.h b/src/client/client.h index cb1227768f9d8..eca81a9262ba7 100644 --- a/src/client/client.h +++ b/src/client/client.h @@ -37,6 +37,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mesh_generator_thread.h" #include "network/address.h" #include "network/peerhandler.h" +#include "clientdynamicinfo.h" #include #define CLIENT_CHAT_MESSAGE_LIMIT_PER_10S 10.0f @@ -248,6 +249,7 @@ class Client : public con::PeerHandler, public InventoryManager, public IGameDef void sendRespawn(); void sendReady(); void sendHaveMedia(const std::vector &tokens); + void sendUpdateClientInfo(const ClientDynamicInfo &info); ClientEnvironment& getEnv() { return m_env; } ITextureSource *tsrc() { return getTextureSource(); } diff --git a/src/client/game.cpp b/src/client/game.cpp index f93bd34a3b6ff..b4db371fab9af 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -72,6 +72,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "version.h" #include "script/scripting_client.h" #include "hud.h" +#include "clientdynamicinfo.h" #if USE_SOUND #include "client/sound_openal.h" @@ -819,12 +820,15 @@ class Game { static const ClientEventHandler clientEventHandler[CLIENTEVENT_MAX]; f32 getSensitivityScaleFactor() const; + ClientDynamicInfo getCurrentDisplayInfo() const; InputHandler *input = nullptr; Client *client = nullptr; Server *server = nullptr; + ClientDynamicInfo client_display_info{}; + IWritableTextureSource *texture_src = nullptr; IWritableShaderSource *shader_src = nullptr; @@ -1082,23 +1086,29 @@ void Game::run() && client->checkPrivilege("fast"); #endif - irr::core::dimension2d previous_screen_size(g_settings->getU16("screen_w"), + v2u32 previous_screen_size(g_settings->getU16("screen_w"), g_settings->getU16("screen_h")); while (m_rendering_engine->run() && !(*kill || g_gamecallback->shutdown_requested || (server && server->isShutdownRequested()))) { - const irr::core::dimension2d ¤t_screen_size = - m_rendering_engine->get_video_driver()->getScreenSize(); + const auto current_display_info = getCurrentDisplayInfo(); + if (!current_display_info.equal(client_display_info)) { + client_display_info = current_display_info; + client->sendUpdateClientInfo(current_display_info); + } + + const auto ¤t_screen_size = current_display_info.screen_size; + // Verify if window size has changed and save it if it's the case // Ensure evaluating settings->getBool after verifying screensize // First condition is cheaper if (previous_screen_size != current_screen_size && current_screen_size != irr::core::dimension2d(0,0) && g_settings->getBool("autosave_screensize")) { - g_settings->setU16("screen_w", current_screen_size.Width); - g_settings->setU16("screen_h", current_screen_size.Height); + g_settings->setU16("screen_w", current_screen_size.X); + g_settings->setU16("screen_h", current_screen_size.Y); previous_screen_size = current_screen_size; } @@ -2453,6 +2463,16 @@ f32 Game::getSensitivityScaleFactor() const return tan(fov_y / 2.0f) * 1.3763818698f; } +ClientDynamicInfo Game::getCurrentDisplayInfo() const +{ + v2u32 screen_size = RenderingEngine::getWindowSize(); + f32 dpi = RenderingEngine::getDisplayDensity() * 96.0f; + f32 gui_scaling = g_settings->getFloat("gui_scaling"); + f32 hud_scaling = g_settings->getFloat("hud_scaling");; + + return { screen_size, dpi, gui_scaling, hud_scaling }; +} + void Game::updateCameraOrientation(CameraOrientation *cam, float dtime) { #ifdef HAVE_TOUCHSCREENGUI diff --git a/src/clientdynamicinfo.h b/src/clientdynamicinfo.h new file mode 100644 index 0000000000000..806705c07d52b --- /dev/null +++ b/src/clientdynamicinfo.h @@ -0,0 +1,19 @@ +#pragma once + +#include "irrTypes.h" + + +struct ClientDynamicInfo +{ + v2u32 screen_size; + f32 dpi; + f32 gui_scaling; + f32 hud_scaling; + + bool equal(const ClientDynamicInfo &other) const { + return screen_size == other.screen_size && + abs(dpi - other.dpi) < 0.001f && + abs(gui_scaling - other.gui_scaling) < 0.001f && + abs(hud_scaling - other.hud_scaling) < 0.001f; + } +}; diff --git a/src/clientiface.h b/src/clientiface.h index 3e7ba4793a773..cc395cc5d6cad 100644 --- a/src/clientiface.h +++ b/src/clientiface.h @@ -28,6 +28,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "network/address.h" #include "porting.h" #include "threading/mutex_auto_lock.h" +#include "clientdynamicinfo.h" #include #include @@ -350,6 +351,9 @@ class RemoteClient void setCachedAddress(const Address &addr) { m_addr = addr; } const Address &getAddress() const { return m_addr; } + void setDynamicInfo(const ClientDynamicInfo &info) { m_dynamic_info = info; } + const ClientDynamicInfo &getDynamicInfo() const { return m_dynamic_info; } + private: // Version is stored in here after INIT before INIT2 u8 m_pending_serialization_version = SER_FMT_VER_INVALID; @@ -360,9 +364,12 @@ class RemoteClient // Cached here so retrieval doesn't have to go to connection API Address m_addr; - // Client sent language code + // Client-sent language code std::string m_lang_code; + // Client-sent dynamic info + ClientDynamicInfo m_dynamic_info{}; + /* Blocks that have been sent to client. - These don't have to be sent again. diff --git a/src/network/clientopcodes.cpp b/src/network/clientopcodes.cpp index 6a78b4652e072..bff3181551724 100644 --- a/src/network/clientopcodes.cpp +++ b/src/network/clientopcodes.cpp @@ -223,4 +223,5 @@ const ServerCommandFactory serverCommandFactoryTable[TOSERVER_NUM_MSG_TYPES] = { "TOSERVER_FIRST_SRP", 1, true }, // 0x50 { "TOSERVER_SRP_BYTES_A", 1, true }, // 0x51 { "TOSERVER_SRP_BYTES_M", 1, true }, // 0x52 + { "TOSERVER_UPDATE_CLIENT_INFO", 1, true }, // 0x53 }; diff --git a/src/network/networkprotocol.h b/src/network/networkprotocol.h index 3923cb85812e6..98608e424b45e 100644 --- a/src/network/networkprotocol.h +++ b/src/network/networkprotocol.h @@ -988,7 +988,15 @@ enum ToServerCommand std::string bytes_M */ - TOSERVER_NUM_MSG_TYPES = 0x53, + TOSERVER_UPDATE_CLIENT_INFO = 0x53, + /* + v2s16 screen_size + f32 dpi + f32 gui_scaling + f32 hud_scaling + */ + + TOSERVER_NUM_MSG_TYPES = 0x54, }; enum AuthMechanism diff --git a/src/network/serveropcodes.cpp b/src/network/serveropcodes.cpp index 12665e7f17fb0..85284d4f3ffea 100644 --- a/src/network/serveropcodes.cpp +++ b/src/network/serveropcodes.cpp @@ -107,6 +107,7 @@ const ToServerCommandHandler toServerCommandTable[TOSERVER_NUM_MSG_TYPES] = { "TOSERVER_FIRST_SRP", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_FirstSrp }, // 0x50 { "TOSERVER_SRP_BYTES_A", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesA }, // 0x51 { "TOSERVER_SRP_BYTES_M", TOSERVER_STATE_NOT_CONNECTED, &Server::handleCommand_SrpBytesM }, // 0x52 + { "TOSERVER_UPDATE_CLIENT_INFO", TOSERVER_STATE_INGAME, &Server::handleCommand_UpdateClientInfo }, // 0x53 }; const static ClientCommandFactory null_command_factory = { "TOCLIENT_NULL", 0, false }; diff --git a/src/network/serverpackethandler.cpp b/src/network/serverpackethandler.cpp index 4b9de488c76b1..0bfa96266dd01 100644 --- a/src/network/serverpackethandler.cpp +++ b/src/network/serverpackethandler.cpp @@ -40,6 +40,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/pointedthing.h" #include "util/serialize.h" #include "util/srp.h" +#include "clientdynamicinfo.h" void Server::handleCommand_Deprecated(NetworkPacket* pkt) { @@ -1839,3 +1840,17 @@ void Server::handleCommand_HaveMedia(NetworkPacket *pkt) } } } + +void Server::handleCommand_UpdateClientInfo(NetworkPacket *pkt) +{ + ClientDynamicInfo info; + *pkt >> info.screen_size.X; + *pkt >> info.screen_size.Y; + *pkt >> info.dpi; + *pkt >> info.gui_scaling; + *pkt >> info.hud_scaling; + + session_t peer_id = pkt->getPeerId(); + RemoteClient *client = getClient(peer_id, CS_Invalid); + client->setDynamicInfo(info); +} diff --git a/src/script/common/c_converter.cpp b/src/script/common/c_converter.cpp index b5ff52f73bcaf..4130d5f3b3111 100644 --- a/src/script/common/c_converter.cpp +++ b/src/script/common/c_converter.cpp @@ -112,6 +112,15 @@ void push_v2s32(lua_State *L, v2s32 p) lua_setfield(L, -2, "y"); } +void push_v2u32(lua_State *L, v2u32 p) +{ + lua_createtable(L, 0, 2); + lua_pushinteger(L, p.X); + lua_setfield(L, -2, "x"); + lua_pushinteger(L, p.Y); + lua_setfield(L, -2, "y"); +} + v2s32 read_v2s32(lua_State *L, int index) { v2s32 p; diff --git a/src/script/common/c_converter.h b/src/script/common/c_converter.h index a14eb91861fab..edbe47bf93b53 100644 --- a/src/script/common/c_converter.h +++ b/src/script/common/c_converter.h @@ -120,6 +120,7 @@ size_t read_stringlist (lua_State *L, int index, void push_v2s16 (lua_State *L, v2s16 p); void push_v2s32 (lua_State *L, v2s32 p); +void push_v2u32 (lua_State *L, v2u32 p); void push_v3s16 (lua_State *L, v3s16 p); void push_aabb3f (lua_State *L, aabb3f box); void push_ARGB8 (lua_State *L, video::SColor color); diff --git a/src/script/lua_api/l_server.cpp b/src/script/lua_api/l_server.cpp index 4b0b45887f5bc..02949f8ae8907 100644 --- a/src/script/lua_api/l_server.cpp +++ b/src/script/lua_api/l_server.cpp @@ -240,6 +240,30 @@ int ModApiServer::l_get_player_information(lua_State *L) lua_pushstring(L, info.lang_code.c_str()); lua_settable(L, table); + if (info.dynamic && info.dynamic->screen_size != v2u32()) { + lua_pushstring(L, "display"); + lua_newtable(L); + int dyn_table = lua_gettop(L); + + lua_pushstring(L, "screen_size"); + push_v2u32(L, info.dynamic->screen_size); + lua_settable(L, dyn_table); + + lua_pushstring(L, "dpi"); + lua_pushnumber(L, info.dynamic->dpi); + lua_settable(L, dyn_table); + + lua_pushstring(L, "gui_scaling"); + lua_pushnumber(L, info.dynamic->gui_scaling); + lua_settable(L, dyn_table); + + lua_pushstring(L, "hud_scaling"); + lua_pushnumber(L, info.dynamic->hud_scaling); + lua_settable(L, dyn_table); + + lua_settable(L, table); + } + #ifndef NDEBUG lua_pushstring(L,"serialization_version"); lua_pushnumber(L, info.ser_vers); diff --git a/src/server.cpp b/src/server.cpp index b6330c96a8397..1289272d1ab07 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1297,6 +1297,8 @@ bool Server::getClientInfo(session_t peer_id, ClientInfo &ret) ret.lang_code = client->getLangCode(); + ret.dynamic = &client->getDynamicInfo(); + return true; } diff --git a/src/server.h b/src/server.h index 2c21f5dfc899c..4cb500215cedb 100644 --- a/src/server.h +++ b/src/server.h @@ -140,6 +140,8 @@ struct ClientInfo { u16 prot_vers; u8 major, minor, patch; std::string vers_string, lang_code; + + const ClientDynamicInfo *dynamic = nullptr; }; class Server : public con::PeerHandler, public MapEventReceiver, @@ -203,6 +205,7 @@ class Server : public con::PeerHandler, public MapEventReceiver, void handleCommand_SrpBytesA(NetworkPacket* pkt); void handleCommand_SrpBytesM(NetworkPacket* pkt); void handleCommand_HaveMedia(NetworkPacket *pkt); + void handleCommand_UpdateClientInfo(NetworkPacket *pkt); void ProcessData(NetworkPacket *pkt);