From 67aa75d444d0e5cfff2728dbbcffd6f95b2fe88b Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Fri, 22 Jan 2021 15:08:57 +0000 Subject: Use JSON for favorites, move server list code to Lua (#10085) Co-authored-by: sfan5 --- src/defaultsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index e8fb18e05..114351d86 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -283,7 +283,7 @@ void set_default_settings(Settings *settings) // Main menu settings->setDefault("main_menu_path", ""); - settings->setDefault("serverlist_file", "favoriteservers.txt"); + settings->setDefault("serverlist_file", "favoriteservers.json"); #if USE_FREETYPE settings->setDefault("freetype", "true"); -- cgit v1.2.3 From 37a05ec8d6cbf9ff4432225cffe78c16fdd0647d Mon Sep 17 00:00:00 2001 From: SmallJoker Date: Sun, 22 Nov 2020 17:49:30 +0100 Subject: Settings: Proper priority hierarchy Remove old defaults system Introduce priority-based fallback list Use new functions for map_meta special functions Change groups to use end tags Unittest changes: * Adapt unittest to the new code * Compare Settings objects --- src/content/subgames.cpp | 24 +-- src/database/database-files.cpp | 15 +- src/database/database-files.h | 4 +- src/defaultsettings.cpp | 4 +- src/defaultsettings.h | 9 +- src/gui/guiKeyChangeMenu.cpp | 2 +- src/main.cpp | 6 +- src/map.cpp | 2 +- src/map_settings_manager.cpp | 67 +++---- src/map_settings_manager.h | 5 +- src/remoteplayer.h | 1 - src/script/lua_api/l_mapgen.cpp | 2 +- src/script/lua_api/l_settings.cpp | 2 +- src/script/scripting_mainmenu.cpp | 2 +- src/server.cpp | 3 + src/server.h | 1 + src/serverenvironment.cpp | 7 +- src/settings.cpp | 300 ++++++++++++++--------------- src/settings.h | 43 +++-- src/unittest/test_map_settings_manager.cpp | 86 ++++++--- src/unittest/test_settings.cpp | 73 +++++-- 21 files changed, 359 insertions(+), 299 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/content/subgames.cpp b/src/content/subgames.cpp index c6350f2dd..e9dc609b0 100644 --- a/src/content/subgames.cpp +++ b/src/content/subgames.cpp @@ -329,18 +329,16 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name, } } - // Override defaults with those provided by the game. - // We clear and reload the defaults because the defaults - // might have been overridden by other subgame config - // files that were loaded before. - g_settings->clearDefaults(); - set_default_settings(g_settings); - - Settings game_defaults; - getGameMinetestConfig(gamespec.path, game_defaults); - game_defaults.removeSecureSettings(); + Settings *game_settings = Settings::getLayer(SL_GAME); + const bool new_game_settings = (game_settings == nullptr); + if (new_game_settings) { + // Called by main-menu without a Server instance running + // -> create and free manually + game_settings = Settings::createLayer(SL_GAME); + } - g_settings->overrideDefaults(&game_defaults); + getGameMinetestConfig(gamespec.path, *game_settings); + game_settings->removeSecureSettings(); infostream << "Initializing world at " << final_path << std::endl; @@ -381,4 +379,8 @@ void loadGameConfAndInitWorld(const std::string &path, const std::string &name, fs::safeWriteToFile(map_meta_path, oss.str()); } + + // The Settings object is no longer needed for created worlds + if (new_game_settings) + delete game_settings; } diff --git a/src/database/database-files.cpp b/src/database/database-files.cpp index 529fb8763..d9e8f24ea 100644 --- a/src/database/database-files.cpp +++ b/src/database/database-files.cpp @@ -122,18 +122,17 @@ void PlayerDatabaseFiles::serialize(RemotePlayer *p, std::ostream &os) args.set("name", p->m_name); // This should not happen - assert(m_sao); - args.setU16("hp", p->m_sao->getHP()); - args.setV3F("position", p->m_sao->getBasePosition()); - args.setFloat("pitch", p->m_sao->getLookPitch()); - args.setFloat("yaw", p->m_sao->getRotation().Y); - args.setU16("breath", p->m_sao->getBreath()); + PlayerSAO *sao = p->getPlayerSAO(); + assert(sao); + args.setU16("hp", sao->getHP()); + args.setV3F("position", sao->getBasePosition()); + args.setFloat("pitch", sao->getLookPitch()); + args.setFloat("yaw", sao->getRotation().Y); + args.setU16("breath", sao->getBreath()); std::string extended_attrs; { // serializeExtraAttributes - PlayerSAO *sao = p->getPlayerSAO(); - assert(sao); Json::Value json_root; const StringMap &attrs = sao->getMeta().getStrings(); diff --git a/src/database/database-files.h b/src/database/database-files.h index a041cb1ff..e647a2e24 100644 --- a/src/database/database-files.h +++ b/src/database/database-files.h @@ -38,8 +38,8 @@ public: void listPlayers(std::vector &res); private: - void deSerialize(RemotePlayer *p, std::istream &is, - const std::string &playername, PlayerSAO *sao); + void deSerialize(RemotePlayer *p, std::istream &is, const std::string &playername, + PlayerSAO *sao); /* serialize() writes a bunch of text that can contain any characters except a '\0', and such an ending that diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 114351d86..d34ec324b 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -27,8 +27,10 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mapgen/mapgen.h" // Mapgen::setDefaultSettings #include "util/string.h" -void set_default_settings(Settings *settings) +void set_default_settings() { + Settings *settings = Settings::createLayer(SL_DEFAULTS); + // Client and server settings->setDefault("language", ""); settings->setDefault("name", ""); diff --git a/src/defaultsettings.h b/src/defaultsettings.h index c81e88502..c239b3c12 100644 --- a/src/defaultsettings.h +++ b/src/defaultsettings.h @@ -25,11 +25,4 @@ class Settings; * initialize basic default settings * @param settings pointer to settings */ -void set_default_settings(Settings *settings); - -/** - * override a default settings by settings from another settings element - * @param settings target settings pointer - * @param from source settings pointer - */ -void override_default_settings(Settings *settings, Settings *from); +void set_default_settings(); diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index eb641d952..4dcb47779 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -248,7 +248,7 @@ bool GUIKeyChangeMenu::acceptInput() { for (key_setting *k : key_settings) { std::string default_key; - g_settings->getDefaultNoEx(k->setting_name, default_key); + Settings::getLayer(SL_DEFAULTS)->getNoEx(k->setting_name, default_key); if (k->key.sym() != default_key) g_settings->set(k->setting_name, k->key.sym()); diff --git a/src/main.cpp b/src/main.cpp index f7238176b..57768dbb2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -487,12 +487,15 @@ static bool create_userdata_path() static bool init_common(const Settings &cmd_args, int argc, char *argv[]) { startup_message(); - set_default_settings(g_settings); + set_default_settings(); // Initialize sockets sockets_init(); atexit(sockets_cleanup); + // Initialize g_settings + Settings::createLayer(SL_GLOBAL); + if (!read_config_file(cmd_args)) return false; @@ -524,6 +527,7 @@ static bool read_config_file(const Settings &cmd_args) // Path of configuration file in use sanity_check(g_settings_path == ""); // Sanity check + if (cmd_args.exists("config")) { bool r = g_settings->readConfigFile(cmd_args.get("config").c_str()); if (!r) { diff --git a/src/map.cpp b/src/map.cpp index aff545921..7c59edbaa 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1184,7 +1184,7 @@ bool Map::isBlockOccluded(MapBlock *block, v3s16 cam_pos_nodes) ServerMap::ServerMap(const std::string &savedir, IGameDef *gamedef, EmergeManager *emerge, MetricsBackend *mb): Map(gamedef), - settings_mgr(g_settings, savedir + DIR_DELIM + "map_meta.txt"), + settings_mgr(savedir + DIR_DELIM + "map_meta.txt"), m_emerge(emerge) { verbosestream<overrideDefaults(user_settings); + m_map_settings = Settings::createLayer(SL_MAP, "[end_of_params]"); + Mapgen::setDefaultSettings(Settings::getLayer(SL_DEFAULTS)); } @@ -49,22 +43,23 @@ MapSettingsManager::~MapSettingsManager() bool MapSettingsManager::getMapSetting( const std::string &name, std::string *value_out) { + // Get from map_meta.txt, then try from all other sources if (m_map_settings->getNoEx(name, *value_out)) return true; // Compatibility kludge - if (m_user_settings == g_settings && name == "seed") - return m_user_settings->getNoEx("fixed_map_seed", *value_out); + if (name == "seed") + return Settings::getLayer(SL_GLOBAL)->getNoEx("fixed_map_seed", *value_out); - return m_user_settings->getNoEx(name, *value_out); + return false; } bool MapSettingsManager::getMapSettingNoiseParams( const std::string &name, NoiseParams *value_out) { - return m_map_settings->getNoiseParams(name, *value_out) || - m_user_settings->getNoiseParams(name, *value_out); + // TODO: Rename to "getNoiseParams" + return m_map_settings->getNoiseParams(name, *value_out); } @@ -77,7 +72,7 @@ bool MapSettingsManager::setMapSetting( if (override_meta) m_map_settings->set(name, value); else - m_map_settings->setDefault(name, value); + Settings::getLayer(SL_GLOBAL)->set(name, value); return true; } @@ -89,7 +84,11 @@ bool MapSettingsManager::setMapSettingNoiseParams( if (mapgen_params) return false; - m_map_settings->setNoiseParams(name, *value, !override_meta); + if (override_meta) + m_map_settings->setNoiseParams(name, *value); + else + Settings::getLayer(SL_GLOBAL)->setNoiseParams(name, *value); + return true; } @@ -104,8 +103,8 @@ bool MapSettingsManager::loadMapMeta() return false; } - if (!m_map_settings->parseConfigLines(is, "[end_of_params]")) { - errorstream << "loadMapMeta: [end_of_params] not found!" << std::endl; + if (!m_map_settings->parseConfigLines(is)) { + errorstream << "loadMapMeta: Format error. '[end_of_params]' missing?" << std::endl; return false; } @@ -116,28 +115,22 @@ bool MapSettingsManager::loadMapMeta() bool MapSettingsManager::saveMapMeta() { // If mapgen params haven't been created yet; abort - if (!mapgen_params) + if (!mapgen_params) { + errorstream << "saveMapMeta: mapgen_params not present!" << std::endl; return false; + } + // Paths set up by subgames.cpp, but not in unittests if (!fs::CreateAllDirs(fs::RemoveLastPathComponent(m_map_meta_path))) { errorstream << "saveMapMeta: could not create dirs to " << m_map_meta_path; return false; } - std::ostringstream oss(std::ios_base::binary); - Settings conf; + mapgen_params->MapgenParams::writeParams(m_map_settings); + mapgen_params->writeParams(m_map_settings); - mapgen_params->MapgenParams::writeParams(&conf); - mapgen_params->writeParams(&conf); - conf.writeLines(oss); - - // NOTE: If there are ever types of map settings other than - // those relating to map generation, save them here - - oss << "[end_of_params]\n"; - - if (!fs::safeWriteToFile(m_map_meta_path, oss.str())) { + if (!m_map_settings->updateConfigFile(m_map_meta_path.c_str())) { errorstream << "saveMapMeta: could not write " << m_map_meta_path << std::endl; return false; @@ -152,23 +145,21 @@ MapgenParams *MapSettingsManager::makeMapgenParams() if (mapgen_params) return mapgen_params; - assert(m_user_settings != NULL); assert(m_map_settings != NULL); // At this point, we have (in order of precedence): - // 1). m_mapgen_settings->m_settings containing map_meta.txt settings or + // 1). SL_MAP containing map_meta.txt settings or // explicit overrides from scripts - // 2). m_mapgen_settings->m_defaults containing script-set mgparams without - // overrides - // 3). g_settings->m_settings containing all user-specified config file + // 2). SL_GLOBAL containing all user-specified config file // settings - // 4). g_settings->m_defaults containing any low-priority settings from + // 3). SL_DEFAULTS containing any low-priority settings from // scripts, e.g. mods using Lua as an enhanced config file) // Now, get the mapgen type so we can create the appropriate MapgenParams std::string mg_name; MapgenType mgtype = getMapSetting("mg_name", &mg_name) ? Mapgen::getMapgenType(mg_name) : MAPGEN_DEFAULT; + if (mgtype == MAPGEN_INVALID) { errorstream << "EmergeManager: mapgen '" << mg_name << "' not valid; falling back to " << diff --git a/src/map_settings_manager.h b/src/map_settings_manager.h index 5baa38455..9258d3032 100644 --- a/src/map_settings_manager.h +++ b/src/map_settings_manager.h @@ -44,8 +44,7 @@ struct MapgenParams; */ class MapSettingsManager { public: - MapSettingsManager(Settings *user_settings, - const std::string &map_meta_path); + MapSettingsManager(const std::string &map_meta_path); ~MapSettingsManager(); // Finalized map generation parameters @@ -71,6 +70,6 @@ public: private: std::string m_map_meta_path; + // TODO: Rename to "m_settings" Settings *m_map_settings; - Settings *m_user_settings; }; diff --git a/src/remoteplayer.h b/src/remoteplayer.h index b82cbc08e..8d086fc5a 100644 --- a/src/remoteplayer.h +++ b/src/remoteplayer.h @@ -140,7 +140,6 @@ public: void onSuccessfulSave(); private: - PlayerSAO *m_sao = nullptr; bool m_dirty = false; diff --git a/src/script/lua_api/l_mapgen.cpp b/src/script/lua_api/l_mapgen.cpp index fad08e1f6..183f20540 100644 --- a/src/script/lua_api/l_mapgen.cpp +++ b/src/script/lua_api/l_mapgen.cpp @@ -982,7 +982,7 @@ int ModApiMapgen::l_set_noiseparams(lua_State *L) bool set_default = !lua_isboolean(L, 3) || readParam(L, 3); - g_settings->setNoiseParams(name, np, set_default); + Settings::getLayer(set_default ? SL_DEFAULTS : SL_GLOBAL)->setNoiseParams(name, np); return 0; } diff --git a/src/script/lua_api/l_settings.cpp b/src/script/lua_api/l_settings.cpp index 33eb02392..bcbaf15fa 100644 --- a/src/script/lua_api/l_settings.cpp +++ b/src/script/lua_api/l_settings.cpp @@ -197,7 +197,7 @@ int LuaSettings::l_set_np_group(lua_State *L) SET_SECURITY_CHECK(L, key); - o->m_settings->setNoiseParams(key, value, false); + o->m_settings->setNoiseParams(key, value); return 0; } diff --git a/src/script/scripting_mainmenu.cpp b/src/script/scripting_mainmenu.cpp index 0f672f917..9b377366e 100644 --- a/src/script/scripting_mainmenu.cpp +++ b/src/script/scripting_mainmenu.cpp @@ -31,7 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc., extern "C" { #include "lualib.h" } - +#include "settings.h" #define MAINMENU_NUM_ASYNC_THREADS 4 diff --git a/src/server.cpp b/src/server.cpp index b5352749c..aba7b6401 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -351,6 +351,7 @@ Server::~Server() // Deinitialize scripting infostream << "Server: Deinitializing scripting" << std::endl; delete m_script; + delete m_game_settings; while (!m_unsent_map_edit_queue.empty()) { delete m_unsent_map_edit_queue.front(); @@ -368,6 +369,8 @@ void Server::init() infostream << "- world: " << m_path_world << std::endl; infostream << "- game: " << m_gamespec.path << std::endl; + m_game_settings = Settings::createLayer(SL_GAME); + // Create world if it doesn't exist try { loadGameConfAndInitWorld(m_path_world, diff --git a/src/server.h b/src/server.h index a7e85d0e1..1dd181794 100644 --- a/src/server.h +++ b/src/server.h @@ -524,6 +524,7 @@ private: u16 m_max_chatmessage_length; // For "dedicated" server list flag bool m_dedicated; + Settings *m_game_settings = nullptr; // Thread can set; step() will throw as ServerError MutexedVariable m_async_fatal_error; diff --git a/src/serverenvironment.cpp b/src/serverenvironment.cpp index 56dbb0632..3d9ba132b 100644 --- a/src/serverenvironment.cpp +++ b/src/serverenvironment.cpp @@ -632,7 +632,7 @@ void ServerEnvironment::saveMeta() // Open file and serialize std::ostringstream ss(std::ios_base::binary); - Settings args; + Settings args("EnvArgsEnd"); args.setU64("game_time", m_game_time); args.setU64("time_of_day", getTimeOfDay()); args.setU64("last_clear_objects_time", m_last_clear_objects_time); @@ -641,7 +641,6 @@ void ServerEnvironment::saveMeta() m_lbm_mgr.createIntroductionTimesString()); args.setU64("day_count", m_day_count); args.writeLines(ss); - ss<<"EnvArgsEnd\n"; if(!fs::safeWriteToFile(path, ss.str())) { @@ -676,9 +675,9 @@ void ServerEnvironment::loadMeta() throw SerializationError("Couldn't load env meta"); } - Settings args; + Settings args("EnvArgsEnd"); - if (!args.parseConfigLines(is, "EnvArgsEnd")) { + if (!args.parseConfigLines(is)) { throw SerializationError("ServerEnvironment::loadMeta(): " "EnvArgsEnd not found!"); } diff --git a/src/settings.cpp b/src/settings.cpp index f30ef34e9..cf2a16aa6 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -33,27 +33,50 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -static Settings main_settings; -Settings *g_settings = &main_settings; +Settings *g_settings = nullptr; std::string g_settings_path; -Settings::~Settings() +Settings *Settings::s_layers[SL_TOTAL_COUNT] = {0}; // Zeroed by compiler +std::unordered_map Settings::s_flags; + + +Settings *Settings::createLayer(SettingsLayer sl, const std::string &end_tag) { - clear(); + if ((int)sl < 0 || sl >= SL_TOTAL_COUNT) + throw new BaseException("Invalid settings layer"); + + Settings *&pos = s_layers[(size_t)sl]; + if (pos) + throw new BaseException("Setting layer " + std::to_string(sl) + " already exists"); + + pos = new Settings(end_tag); + pos->m_settingslayer = sl; + + if (sl == SL_GLOBAL) + g_settings = pos; + return pos; } -Settings & Settings::operator += (const Settings &other) +Settings *Settings::getLayer(SettingsLayer sl) { - if (&other == this) - return *this; + sanity_check((int)sl >= 0 && sl < SL_TOTAL_COUNT); + return s_layers[(size_t)sl]; +} + +Settings::~Settings() +{ MutexAutoLock lock(m_mutex); - MutexAutoLock lock2(other.m_mutex); - updateNoLock(other); + if (m_settingslayer < SL_TOTAL_COUNT) + s_layers[(size_t)m_settingslayer] = nullptr; - return *this; + // Compatibility + if (m_settingslayer == SL_GLOBAL) + g_settings = nullptr; + + clearNoLock(); } @@ -62,11 +85,15 @@ Settings & Settings::operator = (const Settings &other) if (&other == this) return *this; + FATAL_ERROR_IF(m_settingslayer != SL_TOTAL_COUNT && other.m_settingslayer != SL_TOTAL_COUNT, + ("Tried to copy unique Setting layer " + std::to_string(m_settingslayer)).c_str()); + MutexAutoLock lock(m_mutex); MutexAutoLock lock2(other.m_mutex); clearNoLock(); - updateNoLock(other); + m_settings = other.m_settings; + m_callbacks = other.m_callbacks; return *this; } @@ -130,11 +157,11 @@ bool Settings::readConfigFile(const char *filename) if (!is.good()) return false; - return parseConfigLines(is, ""); + return parseConfigLines(is); } -bool Settings::parseConfigLines(std::istream &is, const std::string &end) +bool Settings::parseConfigLines(std::istream &is) { MutexAutoLock lock(m_mutex); @@ -142,7 +169,7 @@ bool Settings::parseConfigLines(std::istream &is, const std::string &end) while (is.good()) { std::getline(is, line); - SettingsParseEvent event = parseConfigObject(line, end, name, value); + SettingsParseEvent event = parseConfigObject(line, name, value); switch (event) { case SPE_NONE: @@ -155,8 +182,8 @@ bool Settings::parseConfigLines(std::istream &is, const std::string &end) case SPE_END: return true; case SPE_GROUP: { - Settings *group = new Settings; - if (!group->parseConfigLines(is, "}")) { + Settings *group = new Settings("}"); + if (!group->parseConfigLines(is)) { delete group; return false; } @@ -169,7 +196,8 @@ bool Settings::parseConfigLines(std::istream &is, const std::string &end) } } - return end.empty(); + // false (failure) if end tag not found + return m_end_tag.empty(); } @@ -179,6 +207,13 @@ void Settings::writeLines(std::ostream &os, u32 tab_depth) const for (const auto &setting_it : m_settings) printEntry(os, setting_it.first, setting_it.second, tab_depth); + + if (!m_end_tag.empty()) { + for (u32 i = 0; i < tab_depth; i++) + os << "\t"; + + os << m_end_tag << "\n"; + } } @@ -193,9 +228,7 @@ void Settings::printEntry(std::ostream &os, const std::string &name, entry.group->writeLines(os, tab_depth + 1); - for (u32 i = 0; i != tab_depth; i++) - os << "\t"; - os << "}\n"; + // Closing bracket handled by writeLines } else { os << name << " = "; @@ -207,8 +240,7 @@ void Settings::printEntry(std::ostream &os, const std::string &name, } -bool Settings::updateConfigObject(std::istream &is, std::ostream &os, - const std::string &end, u32 tab_depth) +bool Settings::updateConfigObject(std::istream &is, std::ostream &os, u32 tab_depth) { SettingEntries::const_iterator it; std::set present_entries; @@ -220,11 +252,11 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, // in the object if existing while (is.good() && !end_found) { std::getline(is, line); - SettingsParseEvent event = parseConfigObject(line, end, name, value); + SettingsParseEvent event = parseConfigObject(line, name, value); switch (event) { case SPE_END: - os << line << (is.eof() ? "" : "\n"); + // Skip end tag. Append later. end_found = true; break; case SPE_MULTILINE: @@ -252,14 +284,13 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, if (it != m_settings.end() && it->second.is_group) { os << line << "\n"; sanity_check(it->second.group != NULL); - was_modified |= it->second.group->updateConfigObject(is, os, - "}", tab_depth + 1); + was_modified |= it->second.group->updateConfigObject(is, os, tab_depth + 1); } else if (it == m_settings.end()) { // Remove by skipping was_modified = true; - Settings removed_group; // Move 'is' to group end + Settings removed_group("}"); // Move 'is' to group end std::stringstream ss; - removed_group.updateConfigObject(is, ss, "}", tab_depth + 1); + removed_group.updateConfigObject(is, ss, tab_depth + 1); break; } else { printEntry(os, name, it->second, tab_depth); @@ -273,6 +304,9 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, } } + if (!line.empty() && is.eof()) + os << "\n"; + // Add any settings in the object that don't exist in the config file yet for (it = m_settings.begin(); it != m_settings.end(); ++it) { if (present_entries.find(it->first) != present_entries.end()) @@ -282,6 +316,12 @@ bool Settings::updateConfigObject(std::istream &is, std::ostream &os, was_modified = true; } + // Append ending tag + if (!m_end_tag.empty()) { + os << m_end_tag << "\n"; + was_modified |= !end_found; + } + return was_modified; } @@ -293,7 +333,7 @@ bool Settings::updateConfigFile(const char *filename) std::ifstream is(filename); std::ostringstream os(std::ios_base::binary); - bool was_modified = updateConfigObject(is, os, ""); + bool was_modified = updateConfigObject(is, os); is.close(); if (!was_modified) @@ -366,29 +406,37 @@ bool Settings::parseCommandLine(int argc, char *argv[], * Getters * ***********/ - -const SettingsEntry &Settings::getEntry(const std::string &name) const +Settings *Settings::getParent() const { - MutexAutoLock lock(m_mutex); + // If the Settings object is within the hierarchy structure, + // iterate towards the origin (0) to find the next fallback layer + if (m_settingslayer >= SL_TOTAL_COUNT) + return nullptr; - SettingEntries::const_iterator n; - if ((n = m_settings.find(name)) == m_settings.end()) { - if ((n = m_defaults.find(name)) == m_defaults.end()) - throw SettingNotFoundException("Setting [" + name + "] not found."); + for (int i = (int)m_settingslayer - 1; i >= 0; --i) { + if (s_layers[i]) + return s_layers[i]; } - return n->second; + + // No parent + return nullptr; } -const SettingsEntry &Settings::getEntryDefault(const std::string &name) const +const SettingsEntry &Settings::getEntry(const std::string &name) const { - MutexAutoLock lock(m_mutex); + { + MutexAutoLock lock(m_mutex); - SettingEntries::const_iterator n; - if ((n = m_defaults.find(name)) == m_defaults.end()) { - throw SettingNotFoundException("Setting [" + name + "] not found."); + SettingEntries::const_iterator n; + if ((n = m_settings.find(name)) != m_settings.end()) + return n->second; } - return n->second; + + if (auto parent = getParent()) + return parent->getEntry(name); + + throw SettingNotFoundException("Setting [" + name + "] not found."); } @@ -412,10 +460,15 @@ const std::string &Settings::get(const std::string &name) const const std::string &Settings::getDefault(const std::string &name) const { - const SettingsEntry &entry = getEntryDefault(name); - if (entry.is_group) + const SettingsEntry *entry; + if (auto parent = getParent()) + entry = &parent->getEntry(name); + else + entry = &getEntry(name); // Bottom of the chain + + if (entry->is_group) throw SettingNotFoundException("Setting [" + name + "] is a group."); - return entry.value; + return entry->value; } @@ -491,29 +544,25 @@ u32 Settings::getFlagStr(const std::string &name, const FlagDesc *flagdesc, u32 *flagmask) const { u32 flags = 0; - u32 mask_default = 0; - std::string value; // Read default value (if there is any) - if (getDefaultNoEx(name, value)) { - flags = std::isdigit(value[0]) - ? stoi(value) - : readFlagString(value, flagdesc, &mask_default); - } + if (auto parent = getParent()) + flags = parent->getFlagStr(name, flagdesc, flagmask); // Apply custom flags "on top" - value = get(name); - u32 flags_user; - u32 mask_user = U32_MAX; - flags_user = std::isdigit(value[0]) - ? stoi(value) // Override default - : readFlagString(value, flagdesc, &mask_user); - - flags &= ~mask_user; - flags |= flags_user; - - if (flagmask) - *flagmask = mask_default | mask_user; + if (m_settings.find(name) != m_settings.end()) { + std::string value = get(name); + u32 flags_user; + u32 mask_user = U32_MAX; + flags_user = std::isdigit(value[0]) + ? stoi(value) // Override default + : readFlagString(value, flagdesc, &mask_user); + + flags &= ~mask_user; + flags |= flags_user; + if (flagmask) + *flagmask |= mask_user; + } return flags; } @@ -521,7 +570,12 @@ u32 Settings::getFlagStr(const std::string &name, const FlagDesc *flagdesc, bool Settings::getNoiseParams(const std::string &name, NoiseParams &np) const { - return getNoiseParamsFromGroup(name, np) || getNoiseParamsFromValue(name, np); + if (getNoiseParamsFromGroup(name, np) || getNoiseParamsFromValue(name, np)) + return true; + if (auto parent = getParent()) + return parent->getNoiseParams(name, np); + + return false; } @@ -583,13 +637,18 @@ bool Settings::exists(const std::string &name) const { MutexAutoLock lock(m_mutex); - return (m_settings.find(name) != m_settings.end() || - m_defaults.find(name) != m_defaults.end()); + if (m_settings.find(name) != m_settings.end()) + return true; + if (auto parent = getParent()) + return parent->exists(name); + return false; } std::vector Settings::getNames() const { + MutexAutoLock lock(m_mutex); + std::vector names; for (const auto &settings_it : m_settings) { names.push_back(settings_it.first); @@ -625,17 +684,6 @@ bool Settings::getNoEx(const std::string &name, std::string &val) const } -bool Settings::getDefaultNoEx(const std::string &name, std::string &val) const -{ - try { - val = getDefault(name); - return true; - } catch (SettingNotFoundException &e) { - return false; - } -} - - bool Settings::getFlag(const std::string &name) const { try { @@ -746,24 +794,25 @@ bool Settings::getFlagStrNoEx(const std::string &name, u32 &val, ***********/ bool Settings::setEntry(const std::string &name, const void *data, - bool set_group, bool set_default) + bool set_group) { - Settings *old_group = NULL; - if (!checkNameValid(name)) return false; if (!set_group && !checkValueValid(*(const std::string *)data)) return false; + Settings *old_group = NULL; { MutexAutoLock lock(m_mutex); - SettingsEntry &entry = set_default ? m_defaults[name] : m_settings[name]; + SettingsEntry &entry = m_settings[name]; old_group = entry.group; entry.value = set_group ? "" : *(const std::string *)data; entry.group = set_group ? *(Settings **)data : NULL; entry.is_group = set_group; + if (set_group) + entry.group->m_end_tag = "}"; } delete old_group; @@ -774,7 +823,7 @@ bool Settings::setEntry(const std::string &name, const void *data, bool Settings::set(const std::string &name, const std::string &value) { - if (!setEntry(name, &value, false, false)) + if (!setEntry(name, &value, false)) return false; doCallbacks(name); @@ -782,9 +831,10 @@ bool Settings::set(const std::string &name, const std::string &value) } +// TODO: Remove this function bool Settings::setDefault(const std::string &name, const std::string &value) { - return setEntry(name, &value, false, true); + return getLayer(SL_DEFAULTS)->set(name, value); } @@ -794,17 +844,7 @@ bool Settings::setGroup(const std::string &name, const Settings &group) // avoid double-free by copying the source Settings *copy = new Settings(); *copy = group; - return setEntry(name, ©, true, false); -} - - -bool Settings::setGroupDefault(const std::string &name, const Settings &group) -{ - // Settings must own the group pointer - // avoid double-free by copying the source - Settings *copy = new Settings(); - *copy = group; - return setEntry(name, ©, true, true); + return setEntry(name, ©, true); } @@ -874,8 +914,7 @@ bool Settings::setFlagStr(const std::string &name, u32 flags, } -bool Settings::setNoiseParams(const std::string &name, - const NoiseParams &np, bool set_default) +bool Settings::setNoiseParams(const std::string &name, const NoiseParams &np) { Settings *group = new Settings; @@ -888,7 +927,7 @@ bool Settings::setNoiseParams(const std::string &name, group->setFloat("lacunarity", np.lacunarity); group->setFlagStr("flags", np.flags, flagdesc_noiseparams, np.flags); - return setEntry(name, &group, true, set_default); + return setEntry(name, &group, true); } @@ -912,20 +951,8 @@ bool Settings::remove(const std::string &name) } -void Settings::clear() -{ - MutexAutoLock lock(m_mutex); - clearNoLock(); -} - -void Settings::clearDefaults() -{ - MutexAutoLock lock(m_mutex); - clearDefaultsNoLock(); -} - SettingsParseEvent Settings::parseConfigObject(const std::string &line, - const std::string &end, std::string &name, std::string &value) + std::string &name, std::string &value) { std::string trimmed_line = trim(line); @@ -933,7 +960,7 @@ SettingsParseEvent Settings::parseConfigObject(const std::string &line, return SPE_NONE; if (trimmed_line[0] == '#') return SPE_COMMENT; - if (trimmed_line == end) + if (trimmed_line == m_end_tag) return SPE_END; size_t pos = trimmed_line.find('='); @@ -952,67 +979,26 @@ SettingsParseEvent Settings::parseConfigObject(const std::string &line, } -void Settings::updateNoLock(const Settings &other) -{ - m_settings.insert(other.m_settings.begin(), other.m_settings.end()); - m_defaults.insert(other.m_defaults.begin(), other.m_defaults.end()); -} - - void Settings::clearNoLock() { - for (SettingEntries::const_iterator it = m_settings.begin(); it != m_settings.end(); ++it) delete it->second.group; m_settings.clear(); - - clearDefaultsNoLock(); } -void Settings::clearDefaultsNoLock() -{ - for (SettingEntries::const_iterator it = m_defaults.begin(); - it != m_defaults.end(); ++it) - delete it->second.group; - m_defaults.clear(); -} void Settings::setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags) { - m_flags[name] = flagdesc; + s_flags[name] = flagdesc; setDefault(name, writeFlagString(flags, flagdesc, U32_MAX)); } -void Settings::overrideDefaults(Settings *other) -{ - for (const auto &setting : other->m_settings) { - if (setting.second.is_group) { - setGroupDefault(setting.first, *setting.second.group); - continue; - } - const FlagDesc *flagdesc = getFlagDescFallback(setting.first); - if (flagdesc) { - // Flags cannot be copied directly. - // 1) Get the current set flags - u32 flags = getFlagStr(setting.first, flagdesc, nullptr); - // 2) Set the flags as defaults - other->setDefault(setting.first, flagdesc, flags); - // 3) Get the newly set flags and override the default setting value - setDefault(setting.first, flagdesc, - other->getFlagStr(setting.first, flagdesc, nullptr)); - continue; - } - // Also covers FlagDesc settings - setDefault(setting.first, setting.second.value); - } -} - const FlagDesc *Settings::getFlagDescFallback(const std::string &name) const { - auto it = m_flags.find(name); - return it == m_flags.end() ? nullptr : it->second; + auto it = s_flags.find(name); + return it == s_flags.end() ? nullptr : it->second; } void Settings::registerChangedCallback(const std::string &name, diff --git a/src/settings.h b/src/settings.h index 6db2f9481..af4cae3cd 100644 --- a/src/settings.h +++ b/src/settings.h @@ -30,7 +30,7 @@ class Settings; struct NoiseParams; // Global objects -extern Settings *g_settings; +extern Settings *g_settings; // Same as Settings::getLayer(SL_GLOBAL); extern std::string g_settings_path; // Type for a settings changed callback function @@ -60,6 +60,14 @@ enum SettingsParseEvent { SPE_MULTILINE, }; +enum SettingsLayer { + SL_DEFAULTS, + SL_GAME, + SL_GLOBAL, + SL_MAP, + SL_TOTAL_COUNT +}; + struct ValueSpec { ValueSpec(ValueType a_type, const char *a_help=NULL) { @@ -92,8 +100,13 @@ typedef std::unordered_map SettingEntries; class Settings { public: - Settings() = default; + static Settings *createLayer(SettingsLayer sl, const std::string &end_tag = ""); + static Settings *getLayer(SettingsLayer sl); + SettingsLayer getLayerType() const { return m_settingslayer; } + Settings(const std::string &end_tag = "") : + m_end_tag(end_tag) + {} ~Settings(); Settings & operator += (const Settings &other); @@ -110,7 +123,7 @@ public: // NOTE: Types of allowed_options are ignored. Returns success. bool parseCommandLine(int argc, char *argv[], std::map &allowed_options); - bool parseConfigLines(std::istream &is, const std::string &end = ""); + bool parseConfigLines(std::istream &is); void writeLines(std::ostream &os, u32 tab_depth=0) const; /*********** @@ -146,7 +159,6 @@ public: bool getGroupNoEx(const std::string &name, Settings *&val) const; bool getNoEx(const std::string &name, std::string &val) const; - bool getDefaultNoEx(const std::string &name, std::string &val) const; bool getFlag(const std::string &name) const; bool getU16NoEx(const std::string &name, u16 &val) const; bool getS16NoEx(const std::string &name, s16 &val) const; @@ -170,11 +182,10 @@ public: // N.B. Groups not allocated with new must be set to NULL in the settings // tree before object destruction. bool setEntry(const std::string &name, const void *entry, - bool set_group, bool set_default); + bool set_group); bool set(const std::string &name, const std::string &value); bool setDefault(const std::string &name, const std::string &value); bool setGroup(const std::string &name, const Settings &group); - bool setGroupDefault(const std::string &name, const Settings &group); bool setBool(const std::string &name, bool value); bool setS16(const std::string &name, s16 value); bool setU16(const std::string &name, u16 value); @@ -185,21 +196,16 @@ public: bool setV3F(const std::string &name, v3f value); bool setFlagStr(const std::string &name, u32 flags, const FlagDesc *flagdesc = nullptr, u32 flagmask = U32_MAX); - bool setNoiseParams(const std::string &name, const NoiseParams &np, - bool set_default=false); + bool setNoiseParams(const std::string &name, const NoiseParams &np); // remove a setting bool remove(const std::string &name); - void clear(); - void clearDefaults(); /************** * Miscellany * **************/ void setDefault(const std::string &name, const FlagDesc *flagdesc, u32 flags); - // Takes the provided setting values and uses them as new defaults - void overrideDefaults(Settings *other); const FlagDesc *getFlagDescFallback(const std::string &name) const; void registerChangedCallback(const std::string &name, @@ -215,9 +221,9 @@ private: ***********************/ SettingsParseEvent parseConfigObject(const std::string &line, - const std::string &end, std::string &name, std::string &value); + std::string &name, std::string &value); bool updateConfigObject(std::istream &is, std::ostream &os, - const std::string &end, u32 tab_depth=0); + u32 tab_depth=0); static bool checkNameValid(const std::string &name); static bool checkValueValid(const std::string &value); @@ -228,9 +234,9 @@ private: /*********** * Getters * ***********/ + Settings *getParent() const; const SettingsEntry &getEntry(const std::string &name) const; - const SettingsEntry &getEntryDefault(const std::string &name) const; // Allow TestSettings to run sanity checks using private functions. friend class TestSettings; @@ -242,14 +248,15 @@ private: void doCallbacks(const std::string &name) const; SettingEntries m_settings; - SettingEntries m_defaults; - std::unordered_map m_flags; - SettingsCallbackMap m_callbacks; + std::string m_end_tag; mutable std::mutex m_callback_mutex; // All methods that access m_settings/m_defaults directly should lock this. mutable std::mutex m_mutex; + static Settings *s_layers[SL_TOTAL_COUNT]; + SettingsLayer m_settingslayer = SL_TOTAL_COUNT; + static std::unordered_map s_flags; }; diff --git a/src/unittest/test_map_settings_manager.cpp b/src/unittest/test_map_settings_manager.cpp index 3d642a9b4..81ca68705 100644 --- a/src/unittest/test_map_settings_manager.cpp +++ b/src/unittest/test_map_settings_manager.cpp @@ -30,7 +30,7 @@ public: TestMapSettingsManager() { TestManager::registerTestModule(this); } const char *getName() { return "TestMapSettingsManager"; } - void makeUserConfig(Settings *conf); + void makeUserConfig(); std::string makeMetaFile(bool make_corrupt); void runTests(IGameDef *gamedef); @@ -65,8 +65,11 @@ void check_noise_params(const NoiseParams *np1, const NoiseParams *np2) } -void TestMapSettingsManager::makeUserConfig(Settings *conf) +void TestMapSettingsManager::makeUserConfig() { + delete Settings::getLayer(SL_GLOBAL); + Settings *conf = Settings::createLayer(SL_GLOBAL); + conf->set("mg_name", "v7"); conf->set("seed", "5678"); conf->set("water_level", "20"); @@ -103,12 +106,11 @@ std::string TestMapSettingsManager::makeMetaFile(bool make_corrupt) void TestMapSettingsManager::testMapSettingsManager() { - Settings user_settings; - makeUserConfig(&user_settings); + makeUserConfig(); std::string test_mapmeta_path = makeMetaFile(false); - MapSettingsManager mgr(&user_settings, test_mapmeta_path); + MapSettingsManager mgr(test_mapmeta_path); std::string value; UASSERT(mgr.getMapSetting("mg_name", &value)); @@ -140,6 +142,12 @@ void TestMapSettingsManager::testMapSettingsManager() mgr.setMapSettingNoiseParams("mgv5_np_height", &script_np_height); mgr.setMapSettingNoiseParams("mgv5_np_factor", &script_np_factor); + { + NoiseParams dummy; + mgr.getMapSettingNoiseParams("mgv5_np_factor", &dummy); + check_noise_params(&dummy, &script_np_factor); + } + // Now make our Params and see if the values are correctly sourced MapgenParams *params = mgr.makeMapgenParams(); UASSERT(params->mgtype == MAPGEN_V5); @@ -188,50 +196,66 @@ void TestMapSettingsManager::testMapSettingsManager() void TestMapSettingsManager::testMapMetaSaveLoad() { - Settings conf; std::string path = getTestTempDirectory() + DIR_DELIM + "foobar" + DIR_DELIM + "map_meta.txt"; + makeUserConfig(); + Settings &conf = *Settings::getLayer(SL_GLOBAL); + + // There cannot be two MapSettingsManager + // copy the mapgen params to compare them + MapgenParams params1, params2; // Create a set of mapgen params and save them to map meta - conf.set("seed", "12345"); - conf.set("water_level", "5"); - MapSettingsManager mgr1(&conf, path); - MapgenParams *params1 = mgr1.makeMapgenParams(); - UASSERT(params1); - UASSERT(mgr1.saveMapMeta()); + { + conf.set("seed", "12345"); + conf.set("water_level", "5"); + MapSettingsManager mgr(path); + MapgenParams *params = mgr.makeMapgenParams(); + UASSERT(params); + params1 = *params; + params1.bparams = nullptr; // No double-free + UASSERT(mgr.saveMapMeta()); + } // Now try loading the map meta to mapgen params - conf.set("seed", "67890"); - conf.set("water_level", "32"); - MapSettingsManager mgr2(&conf, path); - UASSERT(mgr2.loadMapMeta()); - MapgenParams *params2 = mgr2.makeMapgenParams(); - UASSERT(params2); + { + conf.set("seed", "67890"); + conf.set("water_level", "32"); + MapSettingsManager mgr(path); + UASSERT(mgr.loadMapMeta()); + MapgenParams *params = mgr.makeMapgenParams(); + UASSERT(params); + params2 = *params; + params2.bparams = nullptr; // No double-free + } // Check that both results are correct - UASSERTEQ(u64, params1->seed, 12345); - UASSERTEQ(s16, params1->water_level, 5); - UASSERTEQ(u64, params2->seed, 12345); - UASSERTEQ(s16, params2->water_level, 5); + UASSERTEQ(u64, params1.seed, 12345); + UASSERTEQ(s16, params1.water_level, 5); + UASSERTEQ(u64, params2.seed, 12345); + UASSERTEQ(s16, params2.water_level, 5); } void TestMapSettingsManager::testMapMetaFailures() { std::string test_mapmeta_path; - Settings conf; // Check to see if it'll fail on a non-existent map meta file - test_mapmeta_path = "woobawooba/fgdfg/map_meta.txt"; - UASSERT(!fs::PathExists(test_mapmeta_path)); + { + test_mapmeta_path = "woobawooba/fgdfg/map_meta.txt"; + UASSERT(!fs::PathExists(test_mapmeta_path)); - MapSettingsManager mgr1(&conf, test_mapmeta_path); - UASSERT(!mgr1.loadMapMeta()); + MapSettingsManager mgr1(test_mapmeta_path); + UASSERT(!mgr1.loadMapMeta()); + } // Check to see if it'll fail on a corrupt map meta file - test_mapmeta_path = makeMetaFile(true); - UASSERT(fs::PathExists(test_mapmeta_path)); + { + test_mapmeta_path = makeMetaFile(true); + UASSERT(fs::PathExists(test_mapmeta_path)); - MapSettingsManager mgr2(&conf, test_mapmeta_path); - UASSERT(!mgr2.loadMapMeta()); + MapSettingsManager mgr2(test_mapmeta_path); + UASSERT(!mgr2.loadMapMeta()); + } } diff --git a/src/unittest/test_settings.cpp b/src/unittest/test_settings.cpp index f91ba5b67..d2d35c357 100644 --- a/src/unittest/test_settings.cpp +++ b/src/unittest/test_settings.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include "settings.h" +#include "defaultsettings.h" #include "noise.h" class TestSettings : public TestBase { @@ -31,6 +32,7 @@ public: void runTests(IGameDef *gamedef); void testAllSettings(); + void testDefaults(); void testFlagDesc(); static const char *config_text_before; @@ -42,6 +44,7 @@ static TestSettings g_test_instance; void TestSettings::runTests(IGameDef *gamedef) { TEST(testAllSettings); + TEST(testDefaults); TEST(testFlagDesc); } @@ -70,7 +73,8 @@ const char *TestSettings::config_text_before = " with leading whitespace!\n" "\"\"\"\n" "np_terrain = 5, 40, (250, 250, 250), 12341, 5, 0.7, 2.4\n" - "zoop = true"; + "zoop = true\n" + "[dummy_eof_end_tag]\n"; const std::string TestSettings::config_text_after = "leet = 1337\n" @@ -111,12 +115,34 @@ const std::string TestSettings::config_text_after = " animals = cute\n" " num_apples = 4\n" " num_oranges = 53\n" - "}\n"; + "}\n" + "[dummy_eof_end_tag]"; + +void compare_settings(const std::string &name, Settings *a, Settings *b) +{ + auto keys = a->getNames(); + Settings *group1, *group2; + std::string value1, value2; + for (auto &key : keys) { + if (a->getGroupNoEx(key, group1)) { + UASSERT(b->getGroupNoEx(key, group2)); + + compare_settings(name + "->" + key, group1, group2); + continue; + } + + UASSERT(b->getNoEx(key, value1)); + // For identification + value1 = name + "->" + key + "=" + value1; + value2 = name + "->" + key + "=" + a->get(key); + UASSERTCMP(std::string, ==, value2, value1); + } +} void TestSettings::testAllSettings() { try { - Settings s; + Settings s("[dummy_eof_end_tag]"); // Test reading of settings std::istringstream is(config_text_before); @@ -197,21 +223,44 @@ void TestSettings::testAllSettings() is.clear(); is.seekg(0); - UASSERT(s.updateConfigObject(is, os, "", 0) == true); - //printf(">>>> expected config:\n%s\n", TEST_CONFIG_TEXT_AFTER); - //printf(">>>> actual config:\n%s\n", os.str().c_str()); -#if __cplusplus < 201103L - // This test only works in older C++ versions than C++11 because we use unordered_map - UASSERT(os.str() == config_text_after); -#endif + UASSERT(s.updateConfigObject(is, os, 0) == true); + + { + // Confirm settings + Settings s2("[dummy_eof_end_tag]"); + std::istringstream is(config_text_after, std::ios_base::binary); + s2.parseConfigLines(is); + + compare_settings("(main)", &s, &s2); + } + } catch (SettingNotFoundException &e) { UASSERT(!"Setting not found!"); } } +void TestSettings::testDefaults() +{ + Settings *game = Settings::createLayer(SL_GAME); + Settings *def = Settings::getLayer(SL_DEFAULTS); + + def->set("name", "FooBar"); + UASSERT(def->get("name") == "FooBar"); + UASSERT(game->get("name") == "FooBar"); + + game->set("name", "Baz"); + UASSERT(game->get("name") == "Baz"); + + delete game; + + // Restore default settings + delete Settings::getLayer(SL_DEFAULTS); + set_default_settings(); +} + void TestSettings::testFlagDesc() { - Settings s; + Settings &s = *Settings::createLayer(SL_GAME); FlagDesc flagdesc[] = { { "biomes", 0x01 }, { "trees", 0x02 }, @@ -242,4 +291,6 @@ void TestSettings::testFlagDesc() // Enabled: tables s.set("test_flags", "16"); UASSERT(s.getFlagStr("test_flags", flagdesc, nullptr) == 0x10); + + delete &s; } -- cgit v1.2.3 From 3a8c37181a9bf9624f3243e8e884f12ae7692609 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Sun, 7 Feb 2021 15:27:24 +0000 Subject: Use consistent temp folder path (#10892) --- builtin/mainmenu/common.lua | 36 ++++++++---------------------------- doc/menu_lua_api.txt | 1 + src/defaultsettings.cpp | 1 - src/filesys.cpp | 6 ++---- src/script/lua_api/l_mainmenu.cpp | 11 +++++++++++ src/script/lua_api/l_mainmenu.h | 2 ++ 6 files changed, 24 insertions(+), 33 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/mainmenu/common.lua b/builtin/mainmenu/common.lua index 01f9a30b9..cd896f9ec 100644 --- a/builtin/mainmenu/common.lua +++ b/builtin/mainmenu/common.lua @@ -146,35 +146,15 @@ end -------------------------------------------------------------------------------- os.tempfolder = function() - if core.settings:get("TMPFolder") then - return core.settings:get("TMPFolder") .. DIR_DELIM .. "MT_" .. math.random(0,10000) - end - - local filetocheck = os.tmpname() - os.remove(filetocheck) - - -- luacheck: ignore - -- https://blogs.msdn.microsoft.com/vcblog/2014/06/18/c-runtime-crt-features-fixes-and-breaking-changes-in-visual-studio-14-ctp1/ - -- The C runtime (CRT) function called by os.tmpname is tmpnam. - -- Microsofts tmpnam implementation in older CRT / MSVC releases is defective. - -- tmpnam return values starting with a backslash characterize this behavior. - -- https://sourceforge.net/p/mingw-w64/bugs/555/ - -- MinGW tmpnam implementation is forwarded to the CRT directly. - -- https://sourceforge.net/p/mingw-w64/discussion/723797/thread/55520785/ - -- MinGW links to an older CRT release (msvcrt.dll). - -- Due to legal concerns MinGW will never use a newer CRT. - -- - -- Make use of TEMP to compose the temporary filename if an old - -- style tmpnam return value is detected. - if filetocheck:sub(1, 1) == "\\" then - local tempfolder = os.getenv("TEMP") - return tempfolder .. filetocheck - end + local temp = core.get_temp_path() + return temp .. DIR_DELIM .. "MT_" .. math.random(0, 10000) +end - local randname = "MTTempModFolder_" .. math.random(0,10000) - local backstring = filetocheck:reverse() - return filetocheck:sub(0, filetocheck:len() - backstring:find(DIR_DELIM) + 1) .. - randname +-------------------------------------------------------------------------------- +os.tmpname = function() + local path = os.tempfolder() + io.open(path, "w"):close() + return path end -------------------------------------------------------------------------------- diff --git a/doc/menu_lua_api.txt b/doc/menu_lua_api.txt index db49c1736..b3975bc1d 100644 --- a/doc/menu_lua_api.txt +++ b/doc/menu_lua_api.txt @@ -85,6 +85,7 @@ core.get_video_drivers() core.get_mapgen_names([include_hidden=false]) -> table of map generator algorithms registered in the core (possible in async calls) core.get_cache_path() -> path of cache +core.get_temp_path() -> path of temp folder HTTP Requests diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index d34ec324b..41c4922a4 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -461,7 +461,6 @@ void set_default_settings() settings->setDefault("screen_h", "0"); settings->setDefault("fullscreen", "true"); settings->setDefault("touchtarget", "true"); - settings->setDefault("TMPFolder", porting::path_cache); settings->setDefault("touchscreen_threshold","20"); settings->setDefault("fixed_virtual_joystick", "false"); settings->setDefault("virtual_joystick_triggers_aux", "false"); diff --git a/src/filesys.cpp b/src/filesys.cpp index eeba0c564..5ffb4506e 100644 --- a/src/filesys.cpp +++ b/src/filesys.cpp @@ -27,9 +27,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "log.h" #include "config.h" #include "porting.h" -#ifdef __ANDROID__ -#include "settings.h" // For g_settings -#endif namespace fs { @@ -359,8 +356,9 @@ std::string TempPath() compatible with lua's os.tmpname which under the default configuration hardcodes mkstemp("/tmp/lua_XXXXXX"). */ + #ifdef __ANDROID__ - return g_settings->get("TMPFolder"); + return porting::path_cache; #else return DIR_DELIM "tmp"; #endif diff --git a/src/script/lua_api/l_mainmenu.cpp b/src/script/lua_api/l_mainmenu.cpp index 4733c4003..ba7f708a4 100644 --- a/src/script/lua_api/l_mainmenu.cpp +++ b/src/script/lua_api/l_mainmenu.cpp @@ -529,6 +529,7 @@ int ModApiMainMenu::l_get_texturepath(lua_State *L) return 1; } +/******************************************************************************/ int ModApiMainMenu::l_get_texturepath_share(lua_State *L) { std::string gamepath = fs::RemoveRelativePathComponents( @@ -537,12 +538,20 @@ int ModApiMainMenu::l_get_texturepath_share(lua_State *L) return 1; } +/******************************************************************************/ int ModApiMainMenu::l_get_cache_path(lua_State *L) { lua_pushstring(L, fs::RemoveRelativePathComponents(porting::path_cache).c_str()); return 1; } +/******************************************************************************/ +int ModApiMainMenu::l_get_temp_path(lua_State *L) +{ + lua_pushstring(L, fs::TempPath().c_str()); + return 1; +} + /******************************************************************************/ int ModApiMainMenu::l_create_dir(lua_State *L) { const char *path = luaL_checkstring(L, 1); @@ -942,6 +951,7 @@ void ModApiMainMenu::Initialize(lua_State *L, int top) API_FCT(get_texturepath); API_FCT(get_texturepath_share); API_FCT(get_cache_path); + API_FCT(get_temp_path); API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); @@ -975,6 +985,7 @@ void ModApiMainMenu::InitializeAsync(lua_State *L, int top) API_FCT(get_texturepath); API_FCT(get_texturepath_share); API_FCT(get_cache_path); + API_FCT(get_temp_path); API_FCT(create_dir); API_FCT(delete_dir); API_FCT(copy_dir); diff --git a/src/script/lua_api/l_mainmenu.h b/src/script/lua_api/l_mainmenu.h index 580a0df72..49ce7c251 100644 --- a/src/script/lua_api/l_mainmenu.h +++ b/src/script/lua_api/l_mainmenu.h @@ -122,6 +122,8 @@ private: static int l_get_cache_path(lua_State *L); + static int l_get_temp_path(lua_State *L); + static int l_create_dir(lua_State *L); static int l_delete_dir(lua_State *L); -- cgit v1.2.3 From f85e9ab9254e2ae4ac13170f9edea00fb8d931a2 Mon Sep 17 00:00:00 2001 From: rubenwardy Date: Wed, 17 Feb 2021 19:51:28 +0000 Subject: Add nametag background setting and object property (#10937) --- .clang-format | 1 + builtin/settingtypes.txt | 4 ++ doc/lua_api.txt | 18 +++++-- games/devtest/mods/testentities/visuals.lua | 16 +++++- src/activeobjectmgr.h | 3 +- src/client/camera.cpp | 33 +++++-------- src/client/camera.h | 47 +++++++++++++----- src/client/content_cao.cpp | 12 +++-- src/defaultsettings.cpp | 1 + src/object_properties.cpp | 22 +++++++++ src/object_properties.h | 2 + src/script/common/c_content.cpp | 18 +++++++ src/script/common/helper.cpp | 24 ++++++--- src/script/common/helper.h | 3 +- src/script/lua_api/l_object.cpp | 29 +++++++++-- src/util/Optional.h | 77 +++++++++++++++++++++++++++++ src/util/serialize.h | 2 +- 17 files changed, 254 insertions(+), 58 deletions(-) create mode 100644 src/util/Optional.h (limited to 'src/defaultsettings.cpp') diff --git a/.clang-format b/.clang-format index dc7380ffd..0db8ab167 100644 --- a/.clang-format +++ b/.clang-format @@ -29,3 +29,4 @@ AlignAfterOpenBracket: DontAlign ContinuationIndentWidth: 16 ConstructorInitializerIndentWidth: 16 BreakConstructorInitializers: AfterColon +AlwaysBreakTemplateDeclarations: Yes diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 8b6227b37..f800f71ab 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -451,6 +451,10 @@ keymap_decrease_viewing_range_min (View range decrease key) key - [**Basic] +# Whether nametag backgrounds should be shown by default. +# Mods may still set a background. +show_nametag_backgrounds (Show nametag backgrounds by default) bool true + # Enable vertex buffer objects. # This should greatly improve graphics performance. enable_vbo (VBO) bool true diff --git a/doc/lua_api.txt b/doc/lua_api.txt index a09b98924..a9c3bcdd9 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -6274,15 +6274,21 @@ object you are working with still exists. * `get_nametag_attributes()` * returns a table with the attributes of the nametag of an object * { - color = {a=0..255, r=0..255, g=0..255, b=0..255}, text = "", + color = {a=0..255, r=0..255, g=0..255, b=0..255}, + bgcolor = {a=0..255, r=0..255, g=0..255, b=0..255}, } * `set_nametag_attributes(attributes)` * sets the attributes of the nametag of an object * `attributes`: { - color = ColorSpec, text = "My Nametag", + color = ColorSpec, + -- ^ Text color + bgcolor = ColorSpec or false, + -- ^ Sets background color of nametag + -- `false` will cause the background to be set automatically based on user settings + -- Default: false } #### Lua entity only (no-op for other objects) @@ -6956,9 +6962,13 @@ Player properties need to be saved manually. -- For all other objects, a nil or empty string removes the nametag. -- To hide a nametag, set its color alpha to zero. That will disable it entirely. - nametag_color = , - -- Sets color of nametag + -- Sets text color of nametag + + nametag_bgcolor = , + -- Sets background color of nametag + -- `false` will cause the background to be set automatically based on user settings. + -- Default: false infotext = "", -- By default empty, text to be shown when pointed at object diff --git a/games/devtest/mods/testentities/visuals.lua b/games/devtest/mods/testentities/visuals.lua index e3b758329..e382ec44c 100644 --- a/games/devtest/mods/testentities/visuals.lua +++ b/games/devtest/mods/testentities/visuals.lua @@ -103,23 +103,35 @@ minetest.register_entity("testentities:nametag", { on_activate = function(self, staticdata) if staticdata ~= "" then - self.color = minetest.deserialize(staticdata).color + local data = minetest.deserialize(staticdata) + self.color = data.color + self.bgcolor = data.bgcolor else self.color = { r = math.random(0, 255), g = math.random(0, 255), b = math.random(0, 255), } + + if math.random(0, 10) > 5 then + self.bgcolor = { + r = math.random(0, 255), + g = math.random(0, 255), + b = math.random(0, 255), + a = math.random(0, 255), + } + end end assert(self.color) self.object:set_properties({ nametag = tostring(math.random(1000, 10000)), nametag_color = self.color, + nametag_bgcolor = self.bgcolor, }) end, get_staticdata = function(self) - return minetest.serialize({ color = self.color }) + return minetest.serialize({ color = self.color, bgcolor = self.bgcolor }) end, }) diff --git a/src/activeobjectmgr.h b/src/activeobjectmgr.h index 95e7d3344..aa0538e60 100644 --- a/src/activeobjectmgr.h +++ b/src/activeobjectmgr.h @@ -25,7 +25,8 @@ with this program; if not, write to the Free Software Foundation, Inc., class TestClientActiveObjectMgr; class TestServerActiveObjectMgr; -template class ActiveObjectMgr +template +class ActiveObjectMgr { friend class ::TestClientActiveObjectMgr; friend class ::TestServerActiveObjectMgr; diff --git a/src/client/camera.cpp b/src/client/camera.cpp index 9a08254b4..350b685e1 100644 --- a/src/client/camera.cpp +++ b/src/client/camera.cpp @@ -79,6 +79,7 @@ Camera::Camera(MapDrawControl &draw_control, Client *client): m_cache_fov = std::fmax(g_settings->getFloat("fov"), 45.0f); m_arm_inertia = g_settings->getBool("arm_inertia"); m_nametags.clear(); + m_show_nametag_backgrounds = g_settings->getBool("show_nametag_backgrounds"); } Camera::~Camera() @@ -696,18 +697,14 @@ void Camera::drawNametags() v2u32 screensize = driver->getScreenSize(); for (const Nametag *nametag : m_nametags) { - if (nametag->nametag_color.getAlpha() == 0) { - // Enforce hiding nametag, - // because if freetype is enabled, a grey - // shadow can remain. - continue; - } - v3f pos = nametag->parent_node->getAbsolutePosition() + nametag->nametag_pos * BS; + // Nametags are hidden in GenericCAO::updateNametag() + + v3f pos = nametag->parent_node->getAbsolutePosition() + nametag->pos * BS; f32 transformed_pos[4] = { pos.X, pos.Y, pos.Z, 1.0f }; trans.multiplyWith1x4Matrix(transformed_pos); if (transformed_pos[3] > 0) { std::wstring nametag_colorless = - unescape_translate(utf8_to_wide(nametag->nametag_text)); + unescape_translate(utf8_to_wide(nametag->text)); core::dimension2d textsize = font->getDimension( nametag_colorless.c_str()); f32 zDiv = transformed_pos[3] == 0.0f ? 1.0f : @@ -720,26 +717,22 @@ void Camera::drawNametags() core::rect size(0, 0, textsize.Width, textsize.Height); core::rect bg_size(-2, 0, textsize.Width+2, textsize.Height); - video::SColor textColor = nametag->nametag_color; - - bool darkBackground = textColor.getLuminance() > 186; - video::SColor backgroundColor = darkBackground - ? video::SColor(50, 50, 50, 50) - : video::SColor(50, 255, 255, 255); - driver->draw2DRectangle(backgroundColor, bg_size + screen_pos); + auto bgcolor = nametag->getBgColor(m_show_nametag_backgrounds); + if (bgcolor.getAlpha() != 0) + driver->draw2DRectangle(bgcolor, bg_size + screen_pos); font->draw( - translate_string(utf8_to_wide(nametag->nametag_text)).c_str(), - size + screen_pos, textColor); + translate_string(utf8_to_wide(nametag->text)).c_str(), + size + screen_pos, nametag->textcolor); } } } Nametag *Camera::addNametag(scene::ISceneNode *parent_node, - const std::string &nametag_text, video::SColor nametag_color, - const v3f &pos) + const std::string &text, video::SColor textcolor, + Optional bgcolor, const v3f &pos) { - Nametag *nametag = new Nametag(parent_node, nametag_text, nametag_color, pos); + Nametag *nametag = new Nametag(parent_node, text, textcolor, bgcolor, pos); m_nametags.push_back(nametag); return nametag; } diff --git a/src/client/camera.h b/src/client/camera.h index 16a1961be..6fd8d9aa7 100644 --- a/src/client/camera.h +++ b/src/client/camera.h @@ -25,27 +25,47 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include "util/Optional.h" class LocalPlayer; struct MapDrawControl; class Client; class WieldMeshSceneNode; -struct Nametag { +struct Nametag +{ + scene::ISceneNode *parent_node; + std::string text; + video::SColor textcolor; + Optional bgcolor; + v3f pos; + Nametag(scene::ISceneNode *a_parent_node, - const std::string &a_nametag_text, - const video::SColor &a_nametag_color, - const v3f &a_nametag_pos): + const std::string &text, + const video::SColor &textcolor, + const Optional &bgcolor, + const v3f &pos): parent_node(a_parent_node), - nametag_text(a_nametag_text), - nametag_color(a_nametag_color), - nametag_pos(a_nametag_pos) + text(text), + textcolor(textcolor), + bgcolor(bgcolor), + pos(pos) { } - scene::ISceneNode *parent_node; - std::string nametag_text; - video::SColor nametag_color; - v3f nametag_pos; + + video::SColor getBgColor(bool use_fallback) const + { + if (bgcolor) + return bgcolor.value(); + else if (!use_fallback) + return video::SColor(0, 0, 0, 0); + else if (textcolor.getLuminance() > 186) + // Dark background for light text + return video::SColor(50, 50, 50, 50); + else + // Light background for dark text + return video::SColor(50, 255, 255, 255); + } }; enum CameraMode {CAMERA_MODE_FIRST, CAMERA_MODE_THIRD, CAMERA_MODE_THIRD_FRONT}; @@ -164,8 +184,8 @@ public: } Nametag *addNametag(scene::ISceneNode *parent_node, - const std::string &nametag_text, video::SColor nametag_color, - const v3f &pos); + const std::string &text, video::SColor textcolor, + Optional bgcolor, const v3f &pos); void removeNametag(Nametag *nametag); @@ -245,4 +265,5 @@ private: bool m_arm_inertia; std::list m_nametags; + bool m_show_nametag_backgrounds; }; diff --git a/src/client/content_cao.cpp b/src/client/content_cao.cpp index c65977b44..97ae9afc4 100644 --- a/src/client/content_cao.cpp +++ b/src/client/content_cao.cpp @@ -934,7 +934,7 @@ void GenericCAO::updateNametag() if (m_is_local_player) // No nametag for local player return; - if (m_prop.nametag.empty()) { + if (m_prop.nametag.empty() || m_prop.nametag_color.getAlpha() == 0) { // Delete nametag if (m_nametag) { m_client->getCamera()->removeNametag(m_nametag); @@ -952,12 +952,14 @@ void GenericCAO::updateNametag() if (!m_nametag) { // Add nametag m_nametag = m_client->getCamera()->addNametag(node, - m_prop.nametag, m_prop.nametag_color, pos); + m_prop.nametag, m_prop.nametag_color, + m_prop.nametag_bgcolor, pos); } else { // Update nametag - m_nametag->nametag_text = m_prop.nametag; - m_nametag->nametag_color = m_prop.nametag_color; - m_nametag->nametag_pos = pos; + m_nametag->text = m_prop.nametag; + m_nametag->textcolor = m_prop.nametag_color; + m_nametag->bgcolor = m_prop.nametag_bgcolor; + m_nametag->pos = pos; } } diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 41c4922a4..cda953082 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -240,6 +240,7 @@ void set_default_settings() #endif settings->setDefault("enable_particles", "true"); settings->setDefault("arm_inertia", "true"); + settings->setDefault("show_nametag_backgrounds", "true"); settings->setDefault("enable_minimap", "true"); settings->setDefault("minimap_shape_round", "true"); diff --git a/src/object_properties.cpp b/src/object_properties.cpp index f31773060..2eebc27d6 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -24,6 +24,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "util/basic_macros.h" #include +static const video::SColor NULL_BGCOLOR{0, 1, 1, 1}; + ObjectProperties::ObjectProperties() { textures.emplace_back("unknown_object.png"); @@ -62,6 +64,13 @@ std::string ObjectProperties::dump() os << ", nametag=" << nametag; os << ", nametag_color=" << "\"" << nametag_color.getAlpha() << "," << nametag_color.getRed() << "," << nametag_color.getGreen() << "," << nametag_color.getBlue() << "\" "; + + if (nametag_bgcolor) + os << ", nametag_bgcolor=" << "\"" << nametag_color.getAlpha() << "," << nametag_color.getRed() + << "," << nametag_color.getGreen() << "," << nametag_color.getBlue() << "\" "; + else + os << ", nametag_bgcolor=null "; + os << ", selectionbox=" << PP(selectionbox.MinEdge) << "," << PP(selectionbox.MaxEdge); os << ", pointable=" << pointable; os << ", static_save=" << static_save; @@ -121,6 +130,13 @@ void ObjectProperties::serialize(std::ostream &os) const writeU8(os, shaded); writeU8(os, show_on_minimap); + if (!nametag_bgcolor) + writeARGB8(os, NULL_BGCOLOR); + else if (nametag_bgcolor.value().getAlpha() == 0) + writeARGB8(os, video::SColor(0, 0, 0, 0)); + else + writeARGB8(os, nametag_bgcolor.value()); + // Add stuff only at the bottom. // Never remove anything, because we don't want new versions of this } @@ -182,5 +198,11 @@ void ObjectProperties::deSerialize(std::istream &is) if (is.eof()) return; show_on_minimap = tmp; + + auto bgcolor = readARGB8(is); + if (bgcolor != NULL_BGCOLOR) + nametag_bgcolor = bgcolor; + else + nametag_bgcolor = nullopt; } catch (SerializationError &e) {} } diff --git a/src/object_properties.h b/src/object_properties.h index adb483527..db28eebfd 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -24,6 +24,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include +#include "util/Optional.h" struct ObjectProperties { @@ -53,6 +54,7 @@ struct ObjectProperties s8 glow = 0; std::string nametag = ""; video::SColor nametag_color = video::SColor(255, 255, 255, 255); + Optional nametag_bgcolor = nullopt; f32 automatic_face_movement_max_rotation_per_sec = -1.0f; std::string infotext; //! For dropped items, this contains item information. diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index 2f9fbd74b..6995f6b61 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -312,6 +312,17 @@ void read_object_properties(lua_State *L, int index, prop->nametag_color = color; } lua_pop(L, 1); + lua_getfield(L, -1, "nametag_bgcolor"); + if (!lua_isnil(L, -1)) { + if (lua_toboolean(L, -1)) { + video::SColor color; + if (read_color(L, -1, &color)) + prop->nametag_bgcolor = color; + } else { + prop->nametag_bgcolor = nullopt; + } + } + lua_pop(L, 1); lua_getfield(L, -1, "automatic_face_movement_max_rotation_per_sec"); if (lua_isnumber(L, -1)) { @@ -403,6 +414,13 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "nametag"); push_ARGB8(L, prop->nametag_color); lua_setfield(L, -2, "nametag_color"); + if (prop->nametag_bgcolor) { + push_ARGB8(L, prop->nametag_bgcolor.value()); + lua_setfield(L, -2, "nametag_bgcolor"); + } else { + lua_pushboolean(L, false); + lua_setfield(L, -2, "nametag_bgcolor"); + } lua_pushnumber(L, prop->automatic_face_movement_max_rotation_per_sec); lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec"); lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size()); diff --git a/src/script/common/helper.cpp b/src/script/common/helper.cpp index 488144790..fbf24e1b7 100644 --- a/src/script/common/helper.cpp +++ b/src/script/common/helper.cpp @@ -50,22 +50,26 @@ bool LuaHelper::isNaN(lua_State *L, int idx) /* * Read template functions */ -template <> bool LuaHelper::readParam(lua_State *L, int index) +template <> +bool LuaHelper::readParam(lua_State *L, int index) { return lua_toboolean(L, index) != 0; } -template <> s16 LuaHelper::readParam(lua_State *L, int index) +template <> +s16 LuaHelper::readParam(lua_State *L, int index) { return lua_tonumber(L, index); } -template <> int LuaHelper::readParam(lua_State *L, int index) +template <> +int LuaHelper::readParam(lua_State *L, int index) { return luaL_checkint(L, index); } -template <> float LuaHelper::readParam(lua_State *L, int index) +template <> +float LuaHelper::readParam(lua_State *L, int index) { if (isNaN(L, index)) throw LuaError("NaN value is not allowed."); @@ -73,7 +77,8 @@ template <> float LuaHelper::readParam(lua_State *L, int index) return (float)luaL_checknumber(L, index); } -template <> v2s16 LuaHelper::readParam(lua_State *L, int index) +template <> +v2s16 LuaHelper::readParam(lua_State *L, int index) { v2s16 p; CHECK_POS_TAB(index); @@ -88,7 +93,8 @@ template <> v2s16 LuaHelper::readParam(lua_State *L, int index) return p; } -template <> v2f LuaHelper::readParam(lua_State *L, int index) +template <> +v2f LuaHelper::readParam(lua_State *L, int index) { v2f p; CHECK_POS_TAB(index); @@ -103,7 +109,8 @@ template <> v2f LuaHelper::readParam(lua_State *L, int index) return p; } -template <> v3f LuaHelper::readParam(lua_State *L, int index) +template <> +v3f LuaHelper::readParam(lua_State *L, int index) { v3f p; CHECK_POS_TAB(index); @@ -122,7 +129,8 @@ template <> v3f LuaHelper::readParam(lua_State *L, int index) return p; } -template <> std::string LuaHelper::readParam(lua_State *L, int index) +template <> +std::string LuaHelper::readParam(lua_State *L, int index) { size_t length; std::string result; diff --git a/src/script/common/helper.h b/src/script/common/helper.h index 7a794dc9b..6491e73cf 100644 --- a/src/script/common/helper.h +++ b/src/script/common/helper.h @@ -38,7 +38,8 @@ protected: * @param index Lua Index to read * @return read value from Lua */ - template static T readParam(lua_State *L, int index); + template + static T readParam(lua_State *L, int index); /** * Read a value using a template type T from Lua State L and index diff --git a/src/script/lua_api/l_object.cpp b/src/script/lua_api/l_object.cpp index 07aa3f7c9..8ae99b929 100644 --- a/src/script/lua_api/l_object.cpp +++ b/src/script/lua_api/l_object.cpp @@ -737,6 +737,18 @@ int ObjectRef::l_set_nametag_attributes(lua_State *L) } lua_pop(L, 1); + lua_getfield(L, -1, "bgcolor"); + if (!lua_isnil(L, -1)) { + if (lua_toboolean(L, -1)) { + video::SColor color; + if (read_color(L, -1, &color)) + prop->nametag_bgcolor = color; + } else { + prop->nametag_bgcolor = nullopt; + } + } + lua_pop(L, 1); + std::string nametag = getstringfield_default(L, 2, "text", ""); prop->nametag = nametag; @@ -758,13 +770,24 @@ int ObjectRef::l_get_nametag_attributes(lua_State *L) if (!prop) return 0; - video::SColor color = prop->nametag_color; - lua_newtable(L); - push_ARGB8(L, color); + + push_ARGB8(L, prop->nametag_color); lua_setfield(L, -2, "color"); + + if (prop->nametag_bgcolor) { + push_ARGB8(L, prop->nametag_bgcolor.value()); + lua_setfield(L, -2, "bgcolor"); + } else { + lua_pushboolean(L, false); + lua_setfield(L, -2, "bgcolor"); + } + lua_pushstring(L, prop->nametag.c_str()); lua_setfield(L, -2, "text"); + + + return 1; } diff --git a/src/util/Optional.h b/src/util/Optional.h new file mode 100644 index 000000000..9c2842b43 --- /dev/null +++ b/src/util/Optional.h @@ -0,0 +1,77 @@ +/* +Minetest +Copyright (C) 2021 rubenwardy + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU Lesser General Public License as published by +the Free Software Foundation; either version 2.1 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public License along +with this program; if not, write to the Free Software Foundation, Inc., +51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#pragma once + +#include "debug.h" + +struct nullopt_t +{ +}; +constexpr nullopt_t nullopt{}; + +/** + * An implementation of optional for C++11, which aims to be + * compatible with a subset of std::optional features. + * + * Unfortunately, Minetest doesn't use C++17 yet. + * + * @tparam T The type to be stored + */ +template +class Optional +{ + bool m_has_value = false; + T m_value; + +public: + Optional() noexcept {} + Optional(nullopt_t) noexcept {} + Optional(const T &value) noexcept : m_has_value(true), m_value(value) {} + Optional(const Optional &other) noexcept : + m_has_value(other.m_has_value), m_value(other.m_value) + { + } + + void operator=(nullopt_t) noexcept { m_has_value = false; } + + void operator=(const Optional &other) noexcept + { + m_has_value = other.m_has_value; + m_value = other.m_value; + } + + T &value() + { + FATAL_ERROR_IF(!m_has_value, "optional doesn't have value"); + return m_value; + } + + const T &value() const + { + FATAL_ERROR_IF(!m_has_value, "optional doesn't have value"); + return m_value; + } + + const T &value_or(const T &def) const { return m_has_value ? m_value : def; } + + bool has_value() const noexcept { return m_has_value; } + + explicit operator bool() const { return m_has_value; } +}; diff --git a/src/util/serialize.h b/src/util/serialize.h index b3ec28eab..15bdd050d 100644 --- a/src/util/serialize.h +++ b/src/util/serialize.h @@ -290,7 +290,7 @@ inline void writeS8(u8 *data, s8 i) inline void writeS16(u8 *data, s16 i) { - writeU16(data, (u16)i); + writeU16(data, (u16)i); } inline void writeS32(u8 *data, s32 i) -- cgit v1.2.3 From 546ab256b2a5fca86c67f9212fbe5a6a319b2550 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 18 Feb 2021 20:15:39 +0100 Subject: Update buildbot to new MineClone2 repo and set the game name to MineClone2 rather than mineclone2 --- src/defaultsettings.cpp | 2 +- util/buildbot/buildwin32.sh | 4 ++-- util/buildbot/buildwin64.sh | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 6e4e348d0..a1cd61932 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -417,7 +417,7 @@ void set_default_settings() settings->setDefault("max_simultaneous_block_sends_per_client", "40"); settings->setDefault("time_send_interval", "5"); - settings->setDefault("default_game", "mineclone2"); + settings->setDefault("default_game", "MineClone2"); settings->setDefault("motd", ""); settings->setDefault("max_users", "15"); settings->setDefault("creative_mode", "false"); diff --git a/util/buildbot/buildwin32.sh b/util/buildbot/buildwin32.sh index a4238fbd8..c99a0db7a 100755 --- a/util/buildbot/buildwin32.sh +++ b/util/buildbot/buildwin32.sh @@ -4,9 +4,9 @@ set -e CORE_GIT=https://github.com/EliasFleckenstein03/dragonfireclient CORE_BRANCH=master CORE_NAME=dragonfireclient -GAME_GIT=https://git.minetest.land/Wuzzy/MineClone2 +GAME_GIT=https://git.minetest.land/MineClone2/MineClone2 GAME_BRANCH=master -GAME_NAME=mineclone2 +GAME_NAME=MineClone2 dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" if [ $# -ne 1 ]; then diff --git a/util/buildbot/buildwin64.sh b/util/buildbot/buildwin64.sh index 1b680cf5b..6d4ed47a1 100755 --- a/util/buildbot/buildwin64.sh +++ b/util/buildbot/buildwin64.sh @@ -4,9 +4,9 @@ set -e CORE_GIT=https://github.com/EliasFleckenstein03/dragonfireclient CORE_BRANCH=master CORE_NAME=dragonfireclient -GAME_GIT=https://git.minetest.land/Wuzzy/MineClone2 +GAME_GIT=https://git.minetest.land/MineClone2/MineClone2 GAME_BRANCH=master -GAME_NAME=mineclone2 +GAME_NAME=MineClone2 dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" if [ $# -ne 1 ]; then -- cgit v1.2.3 From 827224635bc131dbf4f6e41dd3d78c7a2d94da0f Mon Sep 17 00:00:00 2001 From: Wuzzy Date: Wed, 24 Feb 2021 10:45:30 +0000 Subject: Use "Aux1" key name consistently everywhere --- README.md | 2 +- build/android/icons/aux1_btn.svg | 143 +++++++++++++ build/android/icons/aux_btn.svg | 411 ------------------------------------- builtin/settingtypes.txt | 16 +- src/client/game.cpp | 4 +- src/client/inputhandler.cpp | 4 +- src/client/joystick_controller.cpp | 6 +- src/client/keys.h | 2 +- src/defaultsettings.cpp | 4 +- src/gui/guiKeyChangeMenu.cpp | 6 +- src/gui/touchscreengui.cpp | 18 +- src/gui/touchscreengui.h | 8 +- textures/base/pack/aux1_btn.png | Bin 0 -> 1652 bytes textures/base/pack/aux_btn.png | Bin 1900 -> 0 bytes 14 files changed, 178 insertions(+), 446 deletions(-) create mode 100644 build/android/icons/aux1_btn.svg delete mode 100644 build/android/icons/aux_btn.svg create mode 100644 textures/base/pack/aux1_btn.png delete mode 100644 textures/base/pack/aux_btn.png (limited to 'src/defaultsettings.cpp') diff --git a/README.md b/README.md index 58ec0c821..249f24a16 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ Some can be changed in the key config dialog in the settings tab. | P | Enable/disable pitch move mode | | J | Enable/disable fast mode (needs fast privilege) | | H | Enable/disable noclip mode (needs noclip privilege) | -| E | Move fast in fast mode | +| E | Aux1 (Move fast in fast mode. Games may add special features) | | C | Cycle through camera modes | | V | Cycle through minimap modes | | Shift + V | Change minimap orientation | diff --git a/build/android/icons/aux1_btn.svg b/build/android/icons/aux1_btn.svg new file mode 100644 index 000000000..e0ee97c0c --- /dev/null +++ b/build/android/icons/aux1_btn.svg @@ -0,0 +1,143 @@ + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + Aux1 + + + diff --git a/build/android/icons/aux_btn.svg b/build/android/icons/aux_btn.svg deleted file mode 100644 index 6bbefff67..000000000 --- a/build/android/icons/aux_btn.svg +++ /dev/null @@ -1,411 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - AUX - - diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index f800f71ab..62f1ee2d0 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -75,7 +75,7 @@ free_move (Flying) bool false # If enabled, makes move directions relative to the player's pitch when flying or swimming. pitch_move (Pitch move mode) bool false -# Fast movement (via the "special" key). +# Fast movement (via the "Aux1" key). # This requires the "fast" privilege on the server. fast_move (Fast movement) bool false @@ -99,14 +99,14 @@ invert_mouse (Invert mouse) bool false # Mouse sensitivity multiplier. mouse_sensitivity (Mouse sensitivity) float 0.2 -# If enabled, "special" key instead of "sneak" key is used for climbing down and +# If enabled, "Aux1" key instead of "Sneak" key is used for climbing down and # descending. -aux1_descends (Special key for climbing/descending) bool false +aux1_descends (Aux1 key for climbing/descending) bool false # Double-tapping the jump key toggles fly mode. doubletap_jump (Double tap jump for fly) bool false -# If disabled, "special" key is used to fly fast if both fly and fast mode are +# If disabled, "Aux1" key is used to fly fast if both fly and fast mode are # enabled. always_fly_fast (Always fly and fast) bool true @@ -135,9 +135,9 @@ touchscreen_threshold (Touch screen threshold) int 20 0 100 # If disabled, virtual joystick will center to first-touch's position. fixed_virtual_joystick (Fixed virtual joystick) bool false -# (Android) Use virtual joystick to trigger "aux" button. -# If enabled, virtual joystick will also tap "aux" button when out of main circle. -virtual_joystick_triggers_aux (Virtual joystick triggers aux button) bool false +# (Android) Use virtual joystick to trigger "Aux1" button. +# If enabled, virtual joystick will also tap "Aux1" button when out of main circle. +virtual_joystick_triggers_aux1 (Virtual joystick triggers Aux1 button) bool false # Enable joysticks enable_joysticks (Enable joysticks) bool false @@ -199,7 +199,7 @@ keymap_inventory (Inventory key) key KEY_KEY_I # Key for moving fast in fast mode. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 -keymap_special1 (Special key) key KEY_KEY_E +keymap_aux1 (Aux1 key) key KEY_KEY_E # Key for opening the chat window. # See http://irrlicht.sourceforge.net/docu/namespaceirr.html#a54da2a0e231901735e3da1b0edf72eb3 diff --git a/src/client/game.cpp b/src/client/game.cpp index 3c58fb46f..d4e2fe7c3 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -2415,7 +2415,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam) input->isKeyDown(KeyType::LEFT), input->isKeyDown(KeyType::RIGHT), isKeyDown(KeyType::JUMP), - isKeyDown(KeyType::SPECIAL1), + isKeyDown(KeyType::AUX1), isKeyDown(KeyType::SNEAK), isKeyDown(KeyType::ZOOM), isKeyDown(KeyType::DIG), @@ -2432,7 +2432,7 @@ void Game::updatePlayerControl(const CameraOrientation &cam) ( (u32)(isKeyDown(KeyType::LEFT) & 0x1) << 2) | ( (u32)(isKeyDown(KeyType::RIGHT) & 0x1) << 3) | ( (u32)(isKeyDown(KeyType::JUMP) & 0x1) << 4) | - ( (u32)(isKeyDown(KeyType::SPECIAL1) & 0x1) << 5) | + ( (u32)(isKeyDown(KeyType::AUX1) & 0x1) << 5) | ( (u32)(isKeyDown(KeyType::SNEAK) & 0x1) << 6) | ( (u32)(isKeyDown(KeyType::DIG) & 0x1) << 7) | ( (u32)(isKeyDown(KeyType::PLACE) & 0x1) << 8) | diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index 978baa320..b7e70fa6c 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -35,7 +35,7 @@ void KeyCache::populate() key[KeyType::LEFT] = getKeySetting("keymap_left"); key[KeyType::RIGHT] = getKeySetting("keymap_right"); key[KeyType::JUMP] = getKeySetting("keymap_jump"); - key[KeyType::SPECIAL1] = getKeySetting("keymap_special1"); + key[KeyType::AUX1] = getKeySetting("keymap_aux1"); key[KeyType::SNEAK] = getKeySetting("keymap_sneak"); key[KeyType::DIG] = getKeySetting("keymap_dig"); key[KeyType::PLACE] = getKeySetting("keymap_place"); @@ -219,7 +219,7 @@ void RandomInputHandler::step(float dtime) { static RandomInputHandlerSimData rnd_data[] = { { "keymap_jump", 0.0f, 40 }, - { "keymap_special1", 0.0f, 40 }, + { "keymap_aux1", 0.0f, 40 }, { "keymap_forward", 0.0f, 40 }, { "keymap_left", 0.0f, 40 }, { "keymap_dig", 0.0f, 30 }, diff --git a/src/client/joystick_controller.cpp b/src/client/joystick_controller.cpp index f61ae4ae6..919db5315 100644 --- a/src/client/joystick_controller.cpp +++ b/src/client/joystick_controller.cpp @@ -79,7 +79,7 @@ JoystickLayout create_default_layout() // Accessible without any modifier pressed JLO_B_PB(KeyType::JUMP, bm | 1 << 0, 1 << 0); - JLO_B_PB(KeyType::SPECIAL1, bm | 1 << 1, 1 << 1); + JLO_B_PB(KeyType::AUX1, bm | 1 << 1, 1 << 1); // Accessible with start button not pressed, but four pressed // TODO find usage for button 0 @@ -126,11 +126,11 @@ JoystickLayout create_xbox_layout() // 4 Buttons JLO_B_PB(KeyType::JUMP, 1 << 0, 1 << 0); // A/green JLO_B_PB(KeyType::ESC, 1 << 1, 1 << 1); // B/red - JLO_B_PB(KeyType::SPECIAL1, 1 << 2, 1 << 2); // X/blue + JLO_B_PB(KeyType::AUX1, 1 << 2, 1 << 2); // X/blue JLO_B_PB(KeyType::INVENTORY, 1 << 3, 1 << 3); // Y/yellow // Analog Sticks - JLO_B_PB(KeyType::SPECIAL1, 1 << 11, 1 << 11); // left + JLO_B_PB(KeyType::AUX1, 1 << 11, 1 << 11); // left JLO_B_PB(KeyType::SNEAK, 1 << 12, 1 << 12); // right // Triggers diff --git a/src/client/keys.h b/src/client/keys.h index 60a7a3c45..9f90da6b8 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -32,7 +32,7 @@ public: LEFT, RIGHT, JUMP, - SPECIAL1, + AUX1, SNEAK, AUTOFORWARD, DIG, diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index cda953082..9d155f76c 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -80,7 +80,7 @@ void set_default_settings() settings->setDefault("keymap_drop", "KEY_KEY_Q"); settings->setDefault("keymap_zoom", "KEY_KEY_Z"); settings->setDefault("keymap_inventory", "KEY_KEY_I"); - settings->setDefault("keymap_special1", "KEY_KEY_E"); + settings->setDefault("keymap_aux1", "KEY_KEY_E"); settings->setDefault("keymap_chat", "KEY_KEY_T"); settings->setDefault("keymap_cmd", "/"); settings->setDefault("keymap_cmd_local", "."); @@ -464,7 +464,7 @@ void set_default_settings() settings->setDefault("touchtarget", "true"); settings->setDefault("touchscreen_threshold","20"); settings->setDefault("fixed_virtual_joystick", "false"); - settings->setDefault("virtual_joystick_triggers_aux", "false"); + settings->setDefault("virtual_joystick_triggers_aux1", "false"); settings->setDefault("smooth_lighting", "false"); settings->setDefault("max_simultaneous_block_sends_per_client", "10"); settings->setDefault("emergequeue_limit_diskonly", "16"); diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 4dcb47779..84678b629 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -46,7 +46,7 @@ enum GUI_ID_KEY_BACKWARD_BUTTON, GUI_ID_KEY_LEFT_BUTTON, GUI_ID_KEY_RIGHT_BUTTON, - GUI_ID_KEY_USE_BUTTON, + GUI_ID_KEY_AUX1_BUTTON, GUI_ID_KEY_FLY_BUTTON, GUI_ID_KEY_FAST_BUTTON, GUI_ID_KEY_JUMP_BUTTON, @@ -177,7 +177,7 @@ void GUIKeyChangeMenu::regenerateGui(v2u32 screensize) { core::rect rect(0, 0, option_w, 30 * s); rect += topleft + v2s32(option_x, option_y); - const wchar_t *text = wgettext("\"Special\" = climb down"); + const wchar_t *text = wgettext("\"Aux1\" = climb down"); Environment->addCheckBox(g_settings->getBool("aux1_descends"), rect, this, GUI_ID_CB_AUX1_DESCENDS, text); delete[] text; @@ -416,7 +416,7 @@ void GUIKeyChangeMenu::init_keys() this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); - this->add_key(GUI_ID_KEY_USE_BUTTON, wgettext("Special"), "keymap_special1"); + this->add_key(GUI_ID_KEY_AUX1_BUTTON, wgettext("Aux1"), "keymap_aux1"); this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); diff --git a/src/gui/touchscreengui.cpp b/src/gui/touchscreengui.cpp index e1a971462..78b18c2d9 100644 --- a/src/gui/touchscreengui.cpp +++ b/src/gui/touchscreengui.cpp @@ -40,7 +40,7 @@ const char **button_imagenames = (const char *[]) { "jump_btn.png", "down.png", "zoom.png", - "aux_btn.png" + "aux1_btn.png" }; const char **joystick_imagenames = (const char *[]) { @@ -80,8 +80,8 @@ static irr::EKEY_CODE id2keycode(touch_gui_button_id id) case zoom_id: key = "zoom"; break; - case special1_id: - key = "special1"; + case aux1_id: + key = "aux1"; break; case fly_id: key = "freemove"; @@ -425,7 +425,7 @@ TouchScreenGUI::TouchScreenGUI(IrrlichtDevice *device, IEventReceiver *receiver) m_touchscreen_threshold = g_settings->getU16("touchscreen_threshold"); m_fixed_joystick = g_settings->getBool("fixed_virtual_joystick"); - m_joystick_triggers_special1 = g_settings->getBool("virtual_joystick_triggers_aux"); + m_joystick_triggers_aux1 = g_settings->getBool("virtual_joystick_triggers_aux1"); m_screensize = m_device->getVideoDriver()->getScreenSize(); button_size = MYMIN(m_screensize.Y / 4.5f, porting::getDisplayDensity() * @@ -521,9 +521,9 @@ void TouchScreenGUI::init(ISimpleTextureSource *tsrc) m_screensize.Y - (3 * button_size)), L"z", false); - // init special1/aux button - if (!m_joystick_triggers_special1) - initButton(special1_id, + // init aux1 button + if (!m_joystick_triggers_aux1) + initButton(aux1_id, rect(m_screensize.X - (1.25 * button_size), m_screensize.Y - (2.5 * button_size), m_screensize.X - (0.25 * button_size), @@ -923,7 +923,7 @@ void TouchScreenGUI::translateEvent(const SEvent &event) } if (distance > button_size) { - m_joystick_status[j_special1] = true; + m_joystick_status[j_aux1] = true; // move joystick "button" s32 ndx = button_size * dx / distance - button_size / 2.0f; s32 ndy = button_size * dy / distance - button_size / 2.0f; @@ -1039,7 +1039,7 @@ bool TouchScreenGUI::doubleTapDetection() void TouchScreenGUI::applyJoystickStatus() { for (unsigned int i = 0; i < 5; i++) { - if (i == 4 && !m_joystick_triggers_special1) + if (i == 4 && !m_joystick_triggers_aux1) continue; SEvent translated{}; diff --git a/src/gui/touchscreengui.h b/src/gui/touchscreengui.h index 0349624fa..ad5abae87 100644 --- a/src/gui/touchscreengui.h +++ b/src/gui/touchscreengui.h @@ -39,7 +39,7 @@ typedef enum jump_id = 0, crunch_id, zoom_id, - special1_id, + aux1_id, after_last_element_id, settings_starter_id, rare_controls_starter_id, @@ -69,7 +69,7 @@ typedef enum j_backward, j_left, j_right, - j_special1 + j_aux1 } touch_gui_joystick_move_id; typedef enum @@ -217,7 +217,7 @@ private: // forward, backward, left, right touch_gui_button_id m_joystick_names[5] = { - forward_id, backward_id, left_id, right_id, special1_id}; + forward_id, backward_id, left_id, right_id, aux1_id}; bool m_joystick_status[5] = {false, false, false, false, false}; /* @@ -237,7 +237,7 @@ private: int m_joystick_id = -1; bool m_joystick_has_really_moved = false; bool m_fixed_joystick = false; - bool m_joystick_triggers_special1 = false; + bool m_joystick_triggers_aux1 = false; button_info *m_joystick_btn_off = nullptr; button_info *m_joystick_btn_bg = nullptr; button_info *m_joystick_btn_center = nullptr; diff --git a/textures/base/pack/aux1_btn.png b/textures/base/pack/aux1_btn.png new file mode 100644 index 000000000..8ceb09542 Binary files /dev/null and b/textures/base/pack/aux1_btn.png differ diff --git a/textures/base/pack/aux_btn.png b/textures/base/pack/aux_btn.png deleted file mode 100644 index f589910e8..000000000 Binary files a/textures/base/pack/aux_btn.png and /dev/null differ -- cgit v1.2.3 From 8d89f5f0cc1db47542bd355babad06b6bda54f51 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Mon, 29 Mar 2021 19:55:24 +0200 Subject: Replace fallback font nonsense with automatic per-glyph fallback (#11084) --- builtin/settingtypes.txt | 13 +---- po/minetest.pot | 12 ----- src/CMakeLists.txt | 3 ++ src/client/fontengine.cpp | 95 +++++++++++++++++-------------------- src/client/fontengine.h | 8 ++-- src/defaultsettings.cpp | 5 -- src/irrlicht_changes/CGUITTFont.cpp | 64 +++++++++++++++++++++++-- src/irrlicht_changes/CGUITTFont.h | 7 ++- 8 files changed, 119 insertions(+), 88 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 75efe64da..1f8bf97b7 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -859,7 +859,7 @@ font_path (Regular font path) filepath fonts/Arimo-Regular.ttf font_path_bold (Bold font path) filepath fonts/Arimo-Bold.ttf font_path_italic (Italic font path) filepath fonts/Arimo-Italic.ttf -font_path_bolditalic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf +font_path_bold_italic (Bold and italic font path) filepath fonts/Arimo-BoldItalic.ttf # Font size of the monospace font in point (pt). mono_font_size (Monospace font size) int 15 1 @@ -872,16 +872,7 @@ mono_font_path (Monospace font path) filepath fonts/Cousine-Regular.ttf mono_font_path_bold (Bold monospace font path) filepath fonts/Cousine-Bold.ttf mono_font_path_italic (Italic monospace font path) filepath fonts/Cousine-Italic.ttf -mono_font_path_bolditalic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf - -# Font size of the fallback font in point (pt). -fallback_font_size (Fallback font size) int 15 1 - -# Shadow offset (in pixels) of the fallback font. If 0, then shadow will not be drawn. -fallback_font_shadow (Fallback font shadow) int 1 - -# Opaqueness (alpha) of the shadow behind the fallback font, between 0 and 255. -fallback_font_shadow_alpha (Fallback font shadow alpha) int 128 0 255 +mono_font_path_bold_italic (Bold and italic monospace font path) filepath fonts/Cousine-BoldItalic.ttf # Path of the fallback font. # If “freetype” setting is enabled: Must be a TrueType font. diff --git a/po/minetest.pot b/po/minetest.pot index 9881f5032..b5556d3f3 100644 --- a/po/minetest.pot +++ b/po/minetest.pot @@ -1085,18 +1085,6 @@ msgstr "" msgid "Invalid gamespec." msgstr "" -#. ~ DO NOT TRANSLATE THIS LITERALLY! -#. This is a special string. Put either "no" or "yes" -#. into the translation field (literally). -#. Choose "yes" if the language requires use of the fallback -#. font, "no" otherwise. -#. The fallback font is (normally) required for languages with -#. non-Latin script, like Chinese. -#. When in doubt, test your translation. -#: src/client/fontengine.cpp -msgid "needs_fallback_font" -msgstr "" - #: src/client/game.cpp msgid "Shutting down..." msgstr "" diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8a6eabccc..4bb6877d9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -668,7 +668,10 @@ endif(BUILD_SERVER) # see issue #4638 set(GETTEXT_BLACKLISTED_LOCALES ar + dv he + hi + kn ky ms_Arab th diff --git a/src/client/fontengine.cpp b/src/client/fontengine.cpp index 47218c0d9..0382c2f18 100644 --- a/src/client/fontengine.cpp +++ b/src/client/fontengine.cpp @@ -56,7 +56,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) : readSettings(); - if (m_currentMode == FM_Standard) { + if (m_currentMode != FM_Simple) { g_settings->registerChangedCallback("font_size", font_setting_changed, NULL); g_settings->registerChangedCallback("font_bold", font_setting_changed, NULL); g_settings->registerChangedCallback("font_italic", font_setting_changed, NULL); @@ -66,12 +66,7 @@ FontEngine::FontEngine(gui::IGUIEnvironment* env) : g_settings->registerChangedCallback("font_path_bolditalic", font_setting_changed, NULL); g_settings->registerChangedCallback("font_shadow", font_setting_changed, NULL); g_settings->registerChangedCallback("font_shadow_alpha", font_setting_changed, NULL); - } - else if (m_currentMode == FM_Fallback) { - g_settings->registerChangedCallback("fallback_font_size", font_setting_changed, NULL); g_settings->registerChangedCallback("fallback_font_path", font_setting_changed, NULL); - g_settings->registerChangedCallback("fallback_font_shadow", font_setting_changed, NULL); - g_settings->registerChangedCallback("fallback_font_shadow_alpha", font_setting_changed, NULL); } g_settings->registerChangedCallback("mono_font_path", font_setting_changed, NULL); @@ -101,6 +96,11 @@ void FontEngine::cleanCache() /******************************************************************************/ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) +{ + return getFont(spec, false); +} + +irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec, bool may_fail) { if (spec.mode == FM_Unspecified) { spec.mode = m_currentMode; @@ -112,6 +112,10 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) // Support for those could be added, but who cares? spec.bold = false; spec.italic = false; + } else if (spec.mode == _FM_Fallback) { + // Fallback font doesn't support these either + spec.bold = false; + spec.italic = false; } // Fallback to default size @@ -130,6 +134,13 @@ irr::gui::IGUIFont *FontEngine::getFont(FontSpec spec) else font = initFont(spec); + if (!font && !may_fail) { + errorstream << "Minetest cannot continue without a valid font. " + "Please correct the 'font_path' setting or install the font " + "file in the proper location." << std::endl; + abort(); + } + m_font_cache[spec.getHash()][spec.size] = font; return font; @@ -204,20 +215,9 @@ unsigned int FontEngine::getFontSize(FontMode mode) void FontEngine::readSettings() { if (USE_FREETYPE && g_settings->getBool("freetype")) { - m_default_size[FM_Standard] = g_settings->getU16("font_size"); - m_default_size[FM_Fallback] = g_settings->getU16("fallback_font_size"); - m_default_size[FM_Mono] = g_settings->getU16("mono_font_size"); - - /*~ DO NOT TRANSLATE THIS LITERALLY! - This is a special string. Put either "no" or "yes" - into the translation field (literally). - Choose "yes" if the language requires use of the fallback - font, "no" otherwise. - The fallback font is (normally) required for languages with - non-Latin script, like Chinese. - When in doubt, test your translation. */ - m_currentMode = is_yes(gettext("needs_fallback_font")) ? - FM_Fallback : FM_Standard; + m_default_size[FM_Standard] = g_settings->getU16("font_size"); + m_default_size[_FM_Fallback] = g_settings->getU16("font_size"); + m_default_size[FM_Mono] = g_settings->getU16("mono_font_size"); m_default_bold = g_settings->getBool("font_bold"); m_default_italic = g_settings->getBool("font_italic"); @@ -271,18 +271,8 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) assert(spec.size != FONT_SIZE_UNSPECIFIED); std::string setting_prefix = ""; - - switch (spec.mode) { - case FM_Fallback: - setting_prefix = "fallback_"; - break; - case FM_Mono: - case FM_SimpleMono: - setting_prefix = "mono_"; - break; - default: - break; - } + if (spec.mode == FM_Mono) + setting_prefix = "mono_"; std::string setting_suffix = ""; if (spec.bold) @@ -305,38 +295,41 @@ gui::IGUIFont *FontEngine::initFont(const FontSpec &spec) g_settings->getU16NoEx(setting_prefix + "font_shadow_alpha", font_shadow_alpha); - std::string wanted_font_path; - wanted_font_path = g_settings->get(setting_prefix + "font_path" + setting_suffix); + std::string path_setting; + if (spec.mode == _FM_Fallback) + path_setting = "fallback_font_path"; + else + path_setting = setting_prefix + "font_path" + setting_suffix; std::string fallback_settings[] = { - wanted_font_path, - g_settings->get("fallback_font_path"), - Settings::getLayer(SL_DEFAULTS)->get(setting_prefix + "font_path") + g_settings->get(path_setting), + Settings::getLayer(SL_DEFAULTS)->get(path_setting) }; #if USE_FREETYPE for (const std::string &font_path : fallback_settings) { - irr::gui::IGUIFont *font = gui::CGUITTFont::createTTFont(m_env, + gui::CGUITTFont *font = gui::CGUITTFont::createTTFont(m_env, font_path.c_str(), size, true, true, font_shadow, font_shadow_alpha); - if (font) - return font; - - errorstream << "FontEngine: Cannot load '" << font_path << + if (!font) { + errorstream << "FontEngine: Cannot load '" << font_path << "'. Trying to fall back to another path." << std::endl; - } - + continue; + } - // give up - errorstream << "minetest can not continue without a valid font. " - "Please correct the 'font_path' setting or install the font " - "file in the proper location" << std::endl; + if (spec.mode != _FM_Fallback) { + FontSpec spec2(spec); + spec2.mode = _FM_Fallback; + font->setFallback(getFont(spec2, true)); + } + return font; + } #else - errorstream << "FontEngine: Tried to load freetype fonts but Minetest was" - " not compiled with that library." << std::endl; + errorstream << "FontEngine: Tried to load TTF font but Minetest was" + " compiled without Freetype." << std::endl; #endif - abort(); + return nullptr; } /** initialize a font without freetype */ diff --git a/src/client/fontengine.h b/src/client/fontengine.h index e27ef60e9..3d389ea48 100644 --- a/src/client/fontengine.h +++ b/src/client/fontengine.h @@ -33,7 +33,7 @@ with this program; if not, write to the Free Software Foundation, Inc., enum FontMode : u8 { FM_Standard = 0, FM_Mono, - FM_Fallback, + _FM_Fallback, // do not use directly FM_Simple, FM_SimpleMono, FM_MaxMode, @@ -47,7 +47,7 @@ struct FontSpec { bold(bold), italic(italic) {} - u16 getHash() + u16 getHash() const { return (mode << 2) | (static_cast(bold) << 1) | static_cast(italic); } @@ -132,10 +132,12 @@ public: void readSettings(); private: + irr::gui::IGUIFont *getFont(FontSpec spec, bool may_fail); + /** update content of font cache in case of a setting change made it invalid */ void updateFontCache(); - /** initialize a new font */ + /** initialize a new TTF font */ gui::IGUIFont *initFont(const FontSpec &spec); /** initialize a font without freetype */ diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 9d155f76c..a0d4e9d14 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -304,12 +304,7 @@ void set_default_settings() settings->setDefault("mono_font_path_bold_italic", porting::getDataPath("fonts" DIR_DELIM "Cousine-BoldItalic.ttf")); settings->setDefault("fallback_font_path", porting::getDataPath("fonts" DIR_DELIM "DroidSansFallbackFull.ttf")); - settings->setDefault("fallback_font_shadow", "1"); - settings->setDefault("fallback_font_shadow_alpha", "128"); - std::string font_size_str = std::to_string(TTF_DEFAULT_FONT_SIZE); - - settings->setDefault("fallback_font_size", font_size_str); #else settings->setDefault("freetype", "false"); settings->setDefault("font_path", porting::getDataPath("fonts" DIR_DELIM "mono_dejavu_sans")); diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 960b2320a..8b01e88ae 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -275,7 +275,8 @@ CGUITTFont* CGUITTFont::create(IrrlichtDevice *device, const io::path& filename, //! Constructor. CGUITTFont::CGUITTFont(IGUIEnvironment *env) : use_monochrome(false), use_transparency(true), use_hinting(true), use_auto_hinting(true), -batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0) +batch_load_size(1), Device(0), Environment(env), Driver(0), GlobalKerningWidth(0), GlobalKerningHeight(0), +shadow_offset(0), shadow_alpha(0), fallback(0) { #ifdef _DEBUG setDebugName("CGUITTFont"); @@ -640,7 +641,30 @@ void CGUITTFont::draw(const EnrichedString &text, const core::rect& positio if (current_color < colors.size()) applied_colors.push_back(colors[current_color]); } - offset.X += getWidthFromCharacter(currentChar); + if (n > 0) + { + offset.X += getWidthFromCharacter(currentChar); + } + else if (fallback != 0) + { + // Let the fallback font draw it, this isn't super efficient but hopefully that doesn't matter + wchar_t l1[] = { (wchar_t) currentChar, 0 }, l2 = (wchar_t) previousChar; + + if (visible) + { + // Apply kerning. + offset.X += fallback->getKerningWidth(l1, &l2); + offset.Y += fallback->getKerningHeight(); + + u32 current_color = iter.getPos(); + fallback->draw(core::stringw(l1), + core::rect({offset.X-1, offset.Y-1}, position.LowerRightCorner), // ??? + current_color < colors.size() ? colors[current_color] : video::SColor(255, 255, 255, 255), + false, false, clip); + } + + offset.X += fallback->getDimension(l1).Width; + } previousChar = currentChar; ++iter; @@ -766,6 +790,12 @@ inline u32 CGUITTFont::getWidthFromCharacter(uchar32_t c) const int w = Glyphs[n-1].advance.x / 64; return w; } + if (fallback != 0) + { + wchar_t s[] = { (wchar_t) c, 0 }; + return fallback->getDimension(s).Width; + } + if (c >= 0x2000) return (font_metrics.ascender / 64); else return (font_metrics.ascender / 64) / 2; @@ -789,6 +819,12 @@ inline u32 CGUITTFont::getHeightFromCharacter(uchar32_t c) const s32 height = (font_metrics.ascender / 64) - Glyphs[n-1].offset.Y + Glyphs[n-1].source_rect.getHeight(); return height; } + if (fallback != 0) + { + wchar_t s[] = { (wchar_t) c, 0 }; + return fallback->getDimension(s).Height; + } + if (c >= 0x2000) return (font_metrics.ascender / 64); else return (font_metrics.ascender / 64) / 2; @@ -804,9 +840,9 @@ u32 CGUITTFont::getGlyphIndexByChar(uchar32_t c) const // Get the glyph. u32 glyph = FT_Get_Char_Index(tt_face, c); - // Check for a valid glyph. If it is invalid, attempt to use the replacement character. + // Check for a valid glyph. if (glyph == 0) - glyph = FT_Get_Char_Index(tt_face, core::unicode::UTF_REPLACEMENT_CHARACTER); + return 0; // If our glyph is already loaded, don't bother doing any batch loading code. if (glyph != 0 && Glyphs[glyph - 1].isLoaded) @@ -922,13 +958,26 @@ core::vector2di CGUITTFont::getKerning(const uchar32_t thisLetter, const uchar32 core::vector2di ret(GlobalKerningWidth, GlobalKerningHeight); + u32 n = getGlyphIndexByChar(thisLetter); + + // If we don't have this glyph, ask fallback font + if (n == 0) + { + if (fallback != 0) { + wchar_t l1 = (wchar_t) thisLetter, l2 = (wchar_t) previousLetter; + ret.X = fallback->getKerningWidth(&l1, &l2); + ret.Y = fallback->getKerningHeight(); + } + return ret; + } + // If we don't have kerning, no point in continuing. if (!FT_HAS_KERNING(tt_face)) return ret; // Get the kerning information. FT_Vector v; - FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), getGlyphIndexByChar(thisLetter), FT_KERNING_DEFAULT, &v); + FT_Get_Kerning(tt_face, getGlyphIndexByChar(previousLetter), n, FT_KERNING_DEFAULT, &v); // If we have a scalable font, the return value will be in font points. if (FT_IS_SCALABLE(tt_face)) @@ -960,6 +1009,9 @@ void CGUITTFont::setInvisibleCharacters(const core::ustring& s) video::IImage* CGUITTFont::createTextureFromChar(const uchar32_t& ch) { u32 n = getGlyphIndexByChar(ch); + if (n == 0) + n = getGlyphIndexByChar((uchar32_t) core::unicode::UTF_REPLACEMENT_CHARACTER); + const SGUITTGlyph& glyph = Glyphs[n-1]; CGUITTGlyphPage* page = Glyph_Pages[glyph.glyph_page]; @@ -1147,6 +1199,8 @@ core::array CGUITTFont::addTextSceneNode(const wchar_t* text container.push_back(current_node); } offset.X += getWidthFromCharacter(current_char); + // Note that fallback font handling is missing here (Minetest never uses this) + previous_char = current_char; ++text; } diff --git a/src/irrlicht_changes/CGUITTFont.h b/src/irrlicht_changes/CGUITTFont.h index 310f74f67..a26a1db76 100644 --- a/src/irrlicht_changes/CGUITTFont.h +++ b/src/irrlicht_changes/CGUITTFont.h @@ -269,7 +269,7 @@ namespace gui video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); - virtual void draw(const EnrichedString& text, const core::rect& position, + void draw(const EnrichedString& text, const core::rect& position, video::SColor color, bool hcenter=false, bool vcenter=false, const core::rect* clip=0); @@ -313,6 +313,9 @@ namespace gui //! Get the last glyph page's index. u32 getLastGlyphPageIndex() const { return Glyph_Pages.size() - 1; } + //! Set font that should be used for glyphs not present in ours + void setFallback(gui::IGUIFont* font) { fallback = font; } + //! Create corresponding character's software image copy from the font, //! so you can use this data just like any ordinary video::IImage. //! \param ch The character you need @@ -387,6 +390,8 @@ namespace gui core::ustring Invisible; u32 shadow_offset; u32 shadow_alpha; + + gui::IGUIFont* fallback; }; } // end namespace gui -- cgit v1.2.3 From 34888a914e1eccce8082f45089aec17d5a2815c2 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Fri, 2 Apr 2021 00:19:39 +0200 Subject: Sort out cURL timeouts and increase default --- builtin/settingtypes.txt | 7 +++---- doc/lua_api.txt | 2 +- src/client/clientmedia.cpp | 8 ++------ src/client/clientmedia.h | 1 - src/convert_json.cpp | 47 +--------------------------------------------- src/convert_json.h | 3 --- src/defaultsettings.cpp | 2 +- src/httpfetch.cpp | 21 ++++++++++----------- 8 files changed, 18 insertions(+), 73 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/builtin/settingtypes.txt b/builtin/settingtypes.txt index 67f4877a3..f7412c1ee 100644 --- a/builtin/settingtypes.txt +++ b/builtin/settingtypes.txt @@ -1413,9 +1413,8 @@ enable_ipv6 (IPv6) bool true [*Advanced] -# Default timeout for cURL, stated in milliseconds. -# Only has an effect if compiled with cURL. -curl_timeout (cURL timeout) int 5000 +# Maximum time an interactive request (e.g. server list fetch) may take, stated in milliseconds. +curl_timeout (cURL interactive timeout) int 20000 # Limits number of parallel HTTP requests. Affects: # - Media fetch if server uses remote_media setting. @@ -1424,7 +1423,7 @@ curl_timeout (cURL timeout) int 5000 # Only has an effect if compiled with cURL. curl_parallel_limit (cURL parallel limit) int 8 -# Maximum time in ms a file download (e.g. a mod download) may take. +# Maximum time a file download (e.g. a mod download) may take, stated in milliseconds. curl_file_download_timeout (cURL file download timeout) int 300000 # Makes DirectX work with LuaJIT. Disable if it causes troubles. diff --git a/doc/lua_api.txt b/doc/lua_api.txt index 8a8f57eb3..3630221e3 100644 --- a/doc/lua_api.txt +++ b/doc/lua_api.txt @@ -8394,7 +8394,7 @@ Used by `HTTPApiTable.fetch` and `HTTPApiTable.fetch_async`. url = "http://example.org", timeout = 10, - -- Timeout for connection in seconds. Default is 3 seconds. + -- Timeout for request to be completed in seconds. Default depends on engine settings. method = "GET", "POST", "PUT" or "DELETE" -- The http method to use. Defaults to "GET". diff --git a/src/client/clientmedia.cpp b/src/client/clientmedia.cpp index c4c08c05d..0f9ba5356 100644 --- a/src/client/clientmedia.cpp +++ b/src/client/clientmedia.cpp @@ -216,7 +216,6 @@ void ClientMediaDownloader::initialStep(Client *client) // This is the first time we use httpfetch, so alloc a caller ID m_httpfetch_caller = httpfetch_caller_alloc(); - m_httpfetch_timeout = g_settings->getS32("curl_timeout"); // Set the active fetch limit to curl_parallel_limit or 84, // whichever is greater. This gives us some leeway so that @@ -258,8 +257,6 @@ void ClientMediaDownloader::initialStep(Client *client) remote->baseurl + MTHASHSET_FILE_NAME; fetch_request.caller = m_httpfetch_caller; fetch_request.request_id = m_httpfetch_next_id; // == i - fetch_request.timeout = m_httpfetch_timeout; - fetch_request.connect_timeout = m_httpfetch_timeout; fetch_request.method = HTTP_POST; fetch_request.raw_data = required_hash_set; fetch_request.extra_headers.emplace_back( @@ -432,9 +429,8 @@ void ClientMediaDownloader::startRemoteMediaTransfers() fetch_request.url = url; fetch_request.caller = m_httpfetch_caller; fetch_request.request_id = m_httpfetch_next_id; - fetch_request.timeout = 0; // no data timeout! - fetch_request.connect_timeout = - m_httpfetch_timeout; + fetch_request.timeout = + g_settings->getS32("curl_file_download_timeout"); httpfetch_async(fetch_request); m_remote_file_transfers.insert(std::make_pair( diff --git a/src/client/clientmedia.h b/src/client/clientmedia.h index 5a918535b..e97a0f24b 100644 --- a/src/client/clientmedia.h +++ b/src/client/clientmedia.h @@ -137,7 +137,6 @@ private: // Status of remote transfers unsigned long m_httpfetch_caller; unsigned long m_httpfetch_next_id = 0; - long m_httpfetch_timeout = 0; s32 m_httpfetch_active = 0; s32 m_httpfetch_active_limit = 0; s32 m_outstanding_hash_sets = 0; diff --git a/src/convert_json.cpp b/src/convert_json.cpp index e9ff1e56c..686113fa8 100644 --- a/src/convert_json.cpp +++ b/src/convert_json.cpp @@ -17,56 +17,11 @@ with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#include #include #include +#include #include "convert_json.h" -#include "content/mods.h" -#include "config.h" -#include "log.h" -#include "settings.h" -#include "httpfetch.h" -#include "porting.h" - -Json::Value fetchJsonValue(const std::string &url, - std::vector *extra_headers) -{ - HTTPFetchRequest fetch_request; - HTTPFetchResult fetch_result; - fetch_request.url = url; - fetch_request.caller = HTTPFETCH_SYNC; - - if (extra_headers != NULL) - fetch_request.extra_headers = *extra_headers; - - httpfetch_sync(fetch_request, fetch_result); - - if (!fetch_result.succeeded) { - return Json::Value(); - } - Json::Value root; - std::istringstream stream(fetch_result.data); - - Json::CharReaderBuilder builder; - builder.settings_["collectComments"] = false; - std::string errs; - - if (!Json::parseFromStream(builder, stream, &root, &errs)) { - errorstream << "URL: " << url << std::endl; - errorstream << "Failed to parse json data " << errs << std::endl; - if (fetch_result.data.size() > 100) { - errorstream << "Data (" << fetch_result.data.size() - << " bytes) printed to warningstream." << std::endl; - warningstream << "data: \"" << fetch_result.data << "\"" << std::endl; - } else { - errorstream << "data: \"" << fetch_result.data << "\"" << std::endl; - } - return Json::Value(); - } - - return root; -} void fastWriteJson(const Json::Value &value, std::ostream &to) { diff --git a/src/convert_json.h b/src/convert_json.h index 2c094a946..d1d487e77 100644 --- a/src/convert_json.h +++ b/src/convert_json.h @@ -22,9 +22,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include -Json::Value fetchJsonValue(const std::string &url, - std::vector *extra_headers); - void fastWriteJson(const Json::Value &value, std::ostream &to); std::string fastWriteJson(const Json::Value &value); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index a0d4e9d14..4ecf77c0e 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -56,7 +56,7 @@ void set_default_settings() settings->setDefault("client_unload_unused_data_timeout", "600"); settings->setDefault("client_mapblock_limit", "7500"); settings->setDefault("enable_build_where_you_stand", "false"); - settings->setDefault("curl_timeout", "5000"); + settings->setDefault("curl_timeout", "20000"); settings->setDefault("curl_parallel_limit", "8"); settings->setDefault("curl_file_download_timeout", "300000"); settings->setDefault("curl_verify_cert", "true"); diff --git a/src/httpfetch.cpp b/src/httpfetch.cpp index 65202ce3e..6137782ff 100644 --- a/src/httpfetch.cpp +++ b/src/httpfetch.cpp @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include #include #include -#include +#include #include #include #include "network/socket.h" // for select() @@ -37,13 +37,14 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "settings.h" #include "noise.h" -std::mutex g_httpfetch_mutex; -std::map > g_httpfetch_results; -PcgRandom g_callerid_randomness; +static std::mutex g_httpfetch_mutex; +static std::unordered_map> + g_httpfetch_results; +static PcgRandom g_callerid_randomness; HTTPFetchRequest::HTTPFetchRequest() : timeout(g_settings->getS32("curl_timeout")), - connect_timeout(timeout), + connect_timeout(10 * 1000), useragent(std::string(PROJECT_NAME_C "/") + g_version_hash + " (" + porting::get_sysinfo() + ")") { } @@ -54,7 +55,7 @@ static void httpfetch_deliver_result(const HTTPFetchResult &fetch_result) unsigned long caller = fetch_result.caller; if (caller != HTTPFETCH_DISCARD) { MutexAutoLock lock(g_httpfetch_mutex); - g_httpfetch_results[caller].push(fetch_result); + g_httpfetch_results[caller].emplace(fetch_result); } } @@ -67,8 +68,7 @@ unsigned long httpfetch_caller_alloc() // Check each caller ID except HTTPFETCH_DISCARD const unsigned long discard = HTTPFETCH_DISCARD; for (unsigned long caller = discard + 1; caller != discard; ++caller) { - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) { verbosestream << "httpfetch_caller_alloc: allocating " << caller << std::endl; @@ -127,8 +127,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) MutexAutoLock lock(g_httpfetch_mutex); // Check that caller exists - std::map >::iterator - it = g_httpfetch_results.find(caller); + auto it = g_httpfetch_results.find(caller); if (it == g_httpfetch_results.end()) return false; @@ -138,7 +137,7 @@ bool httpfetch_async_get(unsigned long caller, HTTPFetchResult &fetch_result) return false; // Pop first result - fetch_result = caller_results.front(); + fetch_result = std::move(caller_results.front()); caller_results.pop(); return true; } -- cgit v1.2.3 From 16e5b39e1dbe503684effb11f4b87a641c3e43e6 Mon Sep 17 00:00:00 2001 From: Seth Traverse Date: Tue, 20 Apr 2021 10:23:31 -0700 Subject: Add a key to toggle map block bounds (#11172) It's often useful to know where the map block boundaries are for doing server admin work and the like. Adds three modes: single mapblock, range of 5, and disabled. --- src/client/game.cpp | 2 ++ src/client/hud.cpp | 48 +++++++++++++++++++++++++++++++ src/client/hud.h | 11 +++++++ src/client/inputhandler.cpp | 1 + src/client/keys.h | 1 + src/client/render/core.cpp | 1 + src/defaultsettings.cpp | 1 + src/gui/guiKeyChangeMenu.cpp | 68 +++++++++++++++++++++++--------------------- 8 files changed, 100 insertions(+), 33 deletions(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/client/game.cpp b/src/client/game.cpp index edb054032..b092b95e2 100644 --- a/src/client/game.cpp +++ b/src/client/game.cpp @@ -1932,6 +1932,8 @@ void Game::processKeyInput() toggleCinematic(); } else if (wasKeyDown(KeyType::SCREENSHOT)) { client->makeScreenshot(); + } else if (wasKeyDown(KeyType::TOGGLE_BLOCK_BOUNDS)) { + hud->toggleBlockBounds(); } else if (wasKeyDown(KeyType::TOGGLE_HUD)) { m_game_ui->toggleHud(); } else if (wasKeyDown(KeyType::MINIMAP)) { diff --git a/src/client/hud.cpp b/src/client/hud.cpp index 6d332490c..c58c7e822 100644 --- a/src/client/hud.cpp +++ b/src/client/hud.cpp @@ -862,6 +862,54 @@ void Hud::drawSelectionMesh() } } +void Hud::toggleBlockBounds() +{ + m_block_bounds_mode = static_cast(m_block_bounds_mode + 1); + + if (m_block_bounds_mode >= BLOCK_BOUNDS_MAX) { + m_block_bounds_mode = BLOCK_BOUNDS_OFF; + } +} + +void Hud::drawBlockBounds() +{ + if (m_block_bounds_mode == BLOCK_BOUNDS_OFF) { + return; + } + + video::SMaterial old_material = driver->getMaterial2D(); + driver->setMaterial(m_selection_material); + + v3s16 pos = player->getStandingNodePos(); + + v3s16 blockPos( + floorf((float) pos.X / MAP_BLOCKSIZE), + floorf((float) pos.Y / MAP_BLOCKSIZE), + floorf((float) pos.Z / MAP_BLOCKSIZE) + ); + + v3f offset = intToFloat(client->getCamera()->getOffset(), BS); + + s8 radius = m_block_bounds_mode == BLOCK_BOUNDS_ALL ? 2 : 0; + + v3f halfNode = v3f(BS, BS, BS) / 2.0f; + + for (s8 x = -radius; x <= radius; x++) + for (s8 y = -radius; y <= radius; y++) + for (s8 z = -radius; z <= radius; z++) { + v3s16 blockOffset(x, y, z); + + aabb3f box( + intToFloat((blockPos + blockOffset) * MAP_BLOCKSIZE, BS) - offset - halfNode, + intToFloat(((blockPos + blockOffset) * MAP_BLOCKSIZE) + (MAP_BLOCKSIZE - 1), BS) - offset + halfNode + ); + + driver->draw3DBox(box, video::SColor(255, 255, 0, 0)); + } + + driver->setMaterial(old_material); +} + void Hud::updateSelectionMesh(const v3s16 &camera_offset) { m_camera_offset = camera_offset; diff --git a/src/client/hud.h b/src/client/hud.h index d46545d71..7046a16fb 100644 --- a/src/client/hud.h +++ b/src/client/hud.h @@ -59,6 +59,9 @@ public: Inventory *inventory); ~Hud(); + void toggleBlockBounds(); + void drawBlockBounds(); + void drawHotbar(u16 playeritem); void resizeHotbar(); void drawCrosshair(); @@ -125,6 +128,14 @@ private: scene::SMeshBuffer m_rotation_mesh_buffer; + enum BlockBoundsMode + { + BLOCK_BOUNDS_OFF, + BLOCK_BOUNDS_CURRENT, + BLOCK_BOUNDS_ALL, + BLOCK_BOUNDS_MAX + } m_block_bounds_mode = BLOCK_BOUNDS_OFF; + enum { HIGHLIGHT_BOX, diff --git a/src/client/inputhandler.cpp b/src/client/inputhandler.cpp index b7e70fa6c..980765efa 100644 --- a/src/client/inputhandler.cpp +++ b/src/client/inputhandler.cpp @@ -60,6 +60,7 @@ void KeyCache::populate() key[KeyType::DEC_VOLUME] = getKeySetting("keymap_decrease_volume"); key[KeyType::CINEMATIC] = getKeySetting("keymap_cinematic"); key[KeyType::SCREENSHOT] = getKeySetting("keymap_screenshot"); + key[KeyType::TOGGLE_BLOCK_BOUNDS] = getKeySetting("keymap_toggle_block_bounds"); key[KeyType::TOGGLE_HUD] = getKeySetting("keymap_toggle_hud"); key[KeyType::TOGGLE_CHAT] = getKeySetting("keymap_toggle_chat"); key[KeyType::TOGGLE_FOG] = getKeySetting("keymap_toggle_fog"); diff --git a/src/client/keys.h b/src/client/keys.h index 9f90da6b8..e120a2d92 100644 --- a/src/client/keys.h +++ b/src/client/keys.h @@ -59,6 +59,7 @@ public: DEC_VOLUME, CINEMATIC, SCREENSHOT, + TOGGLE_BLOCK_BOUNDS, TOGGLE_HUD, TOGGLE_CHAT, TOGGLE_FOG, diff --git a/src/client/render/core.cpp b/src/client/render/core.cpp index 92a7137ea..3c4583623 100644 --- a/src/client/render/core.cpp +++ b/src/client/render/core.cpp @@ -76,6 +76,7 @@ void RenderingCore::draw3D() driver->setTransform(video::ETS_WORLD, core::IdentityMatrix); if (!show_hud) return; + hud->drawBlockBounds(); hud->drawSelectionMesh(); if (draw_wield_tool) camera->drawWieldedTool(); diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 4ecf77c0e..871290944 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -97,6 +97,7 @@ void set_default_settings() settings->setDefault("keymap_increase_volume", ""); settings->setDefault("keymap_decrease_volume", ""); settings->setDefault("keymap_cinematic", ""); + settings->setDefault("keymap_toggle_block_bounds", ""); settings->setDefault("keymap_toggle_hud", "KEY_F1"); settings->setDefault("keymap_toggle_chat", "KEY_F2"); settings->setDefault("keymap_toggle_fog", "KEY_F3"); diff --git a/src/gui/guiKeyChangeMenu.cpp b/src/gui/guiKeyChangeMenu.cpp index 84678b629..29d5138f0 100644 --- a/src/gui/guiKeyChangeMenu.cpp +++ b/src/gui/guiKeyChangeMenu.cpp @@ -70,6 +70,7 @@ enum GUI_ID_KEY_MINIMAP_BUTTON, GUI_ID_KEY_SCREENSHOT_BUTTON, GUI_ID_KEY_CHATLOG_BUTTON, + GUI_ID_KEY_BLOCK_BOUNDS_BUTTON, GUI_ID_KEY_HUD_BUTTON, GUI_ID_KEY_FOG_BUTTON, GUI_ID_KEY_DEC_RANGE_BUTTON, @@ -412,37 +413,38 @@ void GUIKeyChangeMenu::add_key(int id, const wchar_t *button_name, const std::st void GUIKeyChangeMenu::init_keys() { - this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); - this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); - this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); - this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); - this->add_key(GUI_ID_KEY_AUX1_BUTTON, wgettext("Aux1"), "keymap_aux1"); - this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); - this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); - this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); - this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); - this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON,wgettext("Prev. item"), "keymap_hotbar_previous"); - this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON,wgettext("Next item"), "keymap_hotbar_next"); - this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom"); - this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode"); - this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap"); - this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); - this->add_key(GUI_ID_KEY_PITCH_MOVE, wgettext("Toggle pitchmove"), "keymap_pitchmove"); - this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); - this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); - this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute"); - this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON,wgettext("Dec. volume"), "keymap_decrease_volume"); - this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON,wgettext("Inc. volume"), "keymap_increase_volume"); - this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward"); - this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); - this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON,wgettext("Screenshot"), "keymap_screenshot"); - this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); - this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min"); - this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min"); - this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); - this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); - this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local"); - this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud"); - this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat"); - this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_fog"); + this->add_key(GUI_ID_KEY_FORWARD_BUTTON, wgettext("Forward"), "keymap_forward"); + this->add_key(GUI_ID_KEY_BACKWARD_BUTTON, wgettext("Backward"), "keymap_backward"); + this->add_key(GUI_ID_KEY_LEFT_BUTTON, wgettext("Left"), "keymap_left"); + this->add_key(GUI_ID_KEY_RIGHT_BUTTON, wgettext("Right"), "keymap_right"); + this->add_key(GUI_ID_KEY_AUX1_BUTTON, wgettext("Aux1"), "keymap_aux1"); + this->add_key(GUI_ID_KEY_JUMP_BUTTON, wgettext("Jump"), "keymap_jump"); + this->add_key(GUI_ID_KEY_SNEAK_BUTTON, wgettext("Sneak"), "keymap_sneak"); + this->add_key(GUI_ID_KEY_DROP_BUTTON, wgettext("Drop"), "keymap_drop"); + this->add_key(GUI_ID_KEY_INVENTORY_BUTTON, wgettext("Inventory"), "keymap_inventory"); + this->add_key(GUI_ID_KEY_HOTBAR_PREV_BUTTON, wgettext("Prev. item"), "keymap_hotbar_previous"); + this->add_key(GUI_ID_KEY_HOTBAR_NEXT_BUTTON, wgettext("Next item"), "keymap_hotbar_next"); + this->add_key(GUI_ID_KEY_ZOOM_BUTTON, wgettext("Zoom"), "keymap_zoom"); + this->add_key(GUI_ID_KEY_CAMERA_BUTTON, wgettext("Change camera"), "keymap_camera_mode"); + this->add_key(GUI_ID_KEY_MINIMAP_BUTTON, wgettext("Toggle minimap"), "keymap_minimap"); + this->add_key(GUI_ID_KEY_FLY_BUTTON, wgettext("Toggle fly"), "keymap_freemove"); + this->add_key(GUI_ID_KEY_PITCH_MOVE, wgettext("Toggle pitchmove"), "keymap_pitchmove"); + this->add_key(GUI_ID_KEY_FAST_BUTTON, wgettext("Toggle fast"), "keymap_fastmove"); + this->add_key(GUI_ID_KEY_NOCLIP_BUTTON, wgettext("Toggle noclip"), "keymap_noclip"); + this->add_key(GUI_ID_KEY_MUTE_BUTTON, wgettext("Mute"), "keymap_mute"); + this->add_key(GUI_ID_KEY_DEC_VOLUME_BUTTON, wgettext("Dec. volume"), "keymap_decrease_volume"); + this->add_key(GUI_ID_KEY_INC_VOLUME_BUTTON, wgettext("Inc. volume"), "keymap_increase_volume"); + this->add_key(GUI_ID_KEY_AUTOFWD_BUTTON, wgettext("Autoforward"), "keymap_autoforward"); + this->add_key(GUI_ID_KEY_CHAT_BUTTON, wgettext("Chat"), "keymap_chat"); + this->add_key(GUI_ID_KEY_SCREENSHOT_BUTTON, wgettext("Screenshot"), "keymap_screenshot"); + this->add_key(GUI_ID_KEY_RANGE_BUTTON, wgettext("Range select"), "keymap_rangeselect"); + this->add_key(GUI_ID_KEY_DEC_RANGE_BUTTON, wgettext("Dec. range"), "keymap_decrease_viewing_range_min"); + this->add_key(GUI_ID_KEY_INC_RANGE_BUTTON, wgettext("Inc. range"), "keymap_increase_viewing_range_min"); + this->add_key(GUI_ID_KEY_CONSOLE_BUTTON, wgettext("Console"), "keymap_console"); + this->add_key(GUI_ID_KEY_CMD_BUTTON, wgettext("Command"), "keymap_cmd"); + this->add_key(GUI_ID_KEY_CMD_LOCAL_BUTTON, wgettext("Local command"), "keymap_cmd_local"); + this->add_key(GUI_ID_KEY_BLOCK_BOUNDS_BUTTON, wgettext("Block bounds"), "keymap_toggle_block_bounds"); + this->add_key(GUI_ID_KEY_HUD_BUTTON, wgettext("Toggle HUD"), "keymap_toggle_hud"); + this->add_key(GUI_ID_KEY_CHATLOG_BUTTON, wgettext("Toggle chat log"), "keymap_toggle_chat"); + this->add_key(GUI_ID_KEY_FOG_BUTTON, wgettext("Toggle fog"), "keymap_toggle_fog"); } -- cgit v1.2.3 From ce0d81a8255886495f5b04ea385b9e37c554db57 Mon Sep 17 00:00:00 2001 From: Elias Fleckenstein Date: Thu, 13 May 2021 08:18:32 +0200 Subject: Change default cheat menu entry height --- src/defaultsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/defaultsettings.cpp') diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index 44b8c91d6..313963c26 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -77,7 +77,7 @@ void set_default_settings() settings->setDefault("cheat_menu_selected_font_color", "(255, 255, 255)"); settings->setDefault("cheat_menu_selected_font_color_alpha", "235"); settings->setDefault("cheat_menu_head_height", "50"); - settings->setDefault("cheat_menu_entry_height", "40"); + settings->setDefault("cheat_menu_entry_height", "35"); settings->setDefault("cheat_menu_entry_width", "200"); // Cheats -- cgit v1.2.3