diff options
79 files changed, 1184 insertions, 1184 deletions
diff --git a/src/being.cpp b/src/being.cpp index ef50d77e..821f7054 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -73,7 +73,7 @@ Being::Being(int id, Type type, int subtype, Map *map): mMoveSpeed = Net::getPlayerHandler()->getDefaultMoveSpeed(); if (getType() == PLAYER) - mShowName = config.getBoolValue("visiblenames"); + mShowName = config.visibleNames; if (getType() == PLAYER || getType() == NPC) setShowName(true); @@ -287,7 +287,7 @@ void Being::setSpeech(const std::string &text, int time) if (!mSpeech.empty()) mSpeechTimer.set(std::min(time, SPEECH_MAX_TIME)); - const int speech = config.getIntValue("speech"); + const int speech = config.speech; if (speech == TEXT_OVERHEAD) { delete mText; @@ -908,7 +908,7 @@ void Being::updateMovement() void Being::drawSpeech(int offsetX, int offsetY) { const int px = getPixelX() - offsetX; - const int speech = config.getIntValue("speech"); + const int speech = config.speech; // Draw speech above this being if (mSpeechTimer.passed()) @@ -979,7 +979,7 @@ void Being::showName() if (getType() == PLAYER) { - if (config.getBoolValue("showgender")) + if (config.showGender) { if (getGender() == Gender::FEMALE) mDisplayName += " \u2640"; @@ -997,7 +997,7 @@ void Being::showName() if (getType() == MONSTER) { - if (config.getBoolValue("showMonstersTakedDamage")) + if (config.showMonstersTakedDamage) { mDisplayName += ", " + toString(getDamageTaken()); } @@ -1234,7 +1234,7 @@ void Being::event(Event::Channel channel, const Event &event) { if (getType() == PLAYER && event.getString("option") == "visiblenames") { - setShowName(config.getBoolValue("visiblenames")); + setShowName(config.visibleNames); } } } diff --git a/src/chatlogger.cpp b/src/chatlogger.cpp index 331e322e..723d2e7b 100644 --- a/src/chatlogger.cpp +++ b/src/chatlogger.cpp @@ -154,8 +154,8 @@ void ChatLogger::writeTo(std::ofstream &file, const std::string &str) const void ChatLogger::setServerName(const std::string &serverName) { mServerName = serverName; - if (mServerName.empty()) - mServerName = config.getStringValue("MostUsedServerName0"); + if (mServerName.empty() && !config.servers.empty()) + mServerName = config.servers.front().hostname; if (mLogFile.is_open()) mLogFile.close(); diff --git a/src/client.cpp b/src/client.cpp index fba54c81..40f41b30 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -91,7 +91,7 @@ std::string errorMessage; LoginData loginData; -Configuration config; /**< XML file configuration reader */ +Config config; /**< Global settings (config.xml) */ Configuration branding; /**< XML branding information reader */ Configuration paths; /**< XML default paths information reader */ Logger *logger; /**< Log object */ @@ -179,7 +179,6 @@ Client::Client(const Options &options): // Set default values for configuration files branding.setDefaultValues(getBrandingDefaults()); paths.setDefaultValues(getPathsDefaults()); - config.setDefaultValues(getConfigDefaults()); // Load branding information if (!options.brandingPath.empty()) @@ -199,7 +198,7 @@ Client::Client(const Options &options): // Configure logger logger->setLogFile(mLocalDataDir + "/mana.log"); - logger->setLogToStandardOut(config.getBoolValue("logToStandardOut")); + logger->setLogToStandardOut(config.logToStandardOut); // Log the mana version logger->log("%s", FULL_VERSION); @@ -262,18 +261,18 @@ Client::Client(const Options &options): // Add the local data directory to PhysicsFS search path resman->addToSearchPath(mLocalDataDir, false); - bool useOpenGL = !mOptions.noOpenGL && config.getBoolValue("opengl"); + bool useOpenGL = !mOptions.noOpenGL && config.opengl; // Set up the transparency option for low CPU when not using OpenGL. - if (!useOpenGL && config.getBoolValue("disableTransparency")) + if (!useOpenGL && config.disableTransparency) Image::SDLdisableTransparency(); VideoSettings videoSettings; - videoSettings.windowMode = static_cast<WindowMode>(config.getIntValue("windowmode")); - videoSettings.width = config.getIntValue("screenwidth"); - videoSettings.height = config.getIntValue("screenheight"); - videoSettings.userScale = config.getIntValue("scale"); - videoSettings.vsync = config.getBoolValue("vsync"); + videoSettings.windowMode = config.windowMode; + videoSettings.width = config.screenWidth; + videoSettings.height = config.screenHeight; + videoSettings.userScale = config.scale; + videoSettings.vsync = config.vsync; videoSettings.openGL = useOpenGL; // Try to set the desired video mode and create the graphics context @@ -322,12 +321,12 @@ Client::Client(const Options &options): // Initialize sound engine try { - if (config.getBoolValue("sound")) + if (config.sound) sound.init(); - sound.setSfxVolume(config.getIntValue("sfxVolume")); - sound.setNotificationsVolume(config.getIntValue("notificationsVolume")); - sound.setMusicVolume(config.getIntValue("musicVolume")); + sound.setSfxVolume(config.sfxVolume); + sound.setNotificationsVolume(config.notificationsVolume); + sound.setMusicVolume(config.musicVolume); } catch (const char *err) { @@ -353,7 +352,7 @@ Client::Client(const Options &options): mCurrentServer.type = options.serverType; loginData.username = options.username; loginData.password = options.password; - loginData.remember = config.getBoolValue("remember"); + loginData.remember = config.remember; loginData.registerLogin = false; if (mCurrentServer.type == ServerType::UNKNOWN && mCurrentServer.port != 0) @@ -384,7 +383,7 @@ Client::Client(const Options &options): chatLogger->setServerName(mCurrentServer.hostname); if (loginData.username.empty() && loginData.remember) - loginData.username = config.getStringValue("username"); + loginData.username = config.username; if (mState != STATE_ERROR) mState = STATE_CHOOSE_SERVER; @@ -392,10 +391,6 @@ Client::Client(const Options &options): // Initialize seconds counter mSecondsCounterId = SDL_AddTimer(1000, nextSecond, nullptr); - listen(Event::ConfigChannel); - - mFpsLimit = config.getIntValue("fpslimit"); - // Initialize PlayerInfo PlayerInfo::init(); } @@ -428,7 +423,9 @@ Client::~Client() logger->log("Quitting"); delete userPalette; - config.write(); + XML::Writer writer(mConfigDir + "/config.xml"); + if (writer.isValid()) + serialize(writer, config); delete logger; @@ -489,7 +486,7 @@ int Client::exec() frame_count++; gui->draw(); graphics->updateScreen(); - mFpsManager.limitFps(mFpsLimit); + mFpsManager.limitFps(config.fpsLimit); } else { @@ -743,7 +740,7 @@ int Client::exec() mOptions.character, CharSelectDialog::Choose)) { ((CharSelectDialog*) mCurrentDialog)->selectByName( - config.getStringValue("lastCharacter"), + config.lastCharacter, mOptions.chooseDefault ? CharSelectDialog::Choose : CharSelectDialog::Focus); @@ -777,7 +774,7 @@ int Client::exec() case STATE_GAME: logger->log("Memorizing selected character %s", local_player->getName().c_str()); - config.setValue("lastCharacter", local_player->getName()); + config.lastCharacter = local_player->getName(); // Fade out logon-music here too to give the desired effect // of "flowing" into the game. @@ -963,16 +960,6 @@ void Client::showErrorDialog(const std::string &message, State state) showOkDialog(_("Error"), message, state); } -void Client::event(Event::Channel channel, const Event &event) -{ - if (channel == Event::ConfigChannel && - event.getType() == Event::ConfigOptionChanged && - event.getString("option") == "fpslimit") - { - mFpsLimit = config.getIntValue("fpslimit"); - } -} - void Client::action(const gcn::ActionEvent &event) { Window *window = nullptr; @@ -1102,33 +1089,15 @@ void Client::initHomeDir() void Client::initConfiguration() { // Fill configuration with defaults - config.setValue("updatehost", branding.getValue("defaultUpdateHost", - std::string())); - - // Checking if the configuration file exists... otherwise create it with - // default options. - FILE *configFile = nullptr; - std::string configPath; + config.updatehost = branding.getValue("defaultUpdateHost", std::string()); - configPath = mConfigDir + "/config.xml"; + const std::string configPath = mConfigDir + "/config.xml"; + XML::Document doc(configPath, false); - configFile = fopen(configPath.c_str(), "r"); - - // If we can't read it, it doesn't exist ! - if (!configFile) - { - // We reopen the file in write mode and we create it - configFile = fopen(configPath.c_str(), "wt"); - } - if (!configFile) - { - logger->log("Can't create %s. Using defaults.", configPath.c_str()); - } + if (doc.rootNode() && doc.rootNode().name() == "configuration") + deserialize(doc.rootNode(), config); else - { - fclose(configFile); - config.init(configPath); - } + logger->log("Couldn't read configuration file: %s", configPath.c_str()); } /** @@ -1139,7 +1108,7 @@ void Client::initUpdatesDir() { // If updatesHost is currently empty, fill it from config file if (mUpdateHost.empty()) - mUpdateHost = config.getStringValue("updatehost"); + mUpdateHost = config.updatehost; // Exit on empty update host. if (mUpdateHost.empty()) @@ -1217,17 +1186,16 @@ void Client::initScreenshotDir() mScreenshotDir = std::string(PHYSFS_getUserDir()) + "Desktop"; #endif - if (config.getBoolValue("useScreenshotDirectorySuffix")) + if (config.useScreenshotDirectorySuffix) { - std::string configScreenshotSuffix = - config.getValue("screenshotDirectorySuffix", - branding.getValue("appShort", "Mana")); + std::string screenshotSuffix = config.screenshotDirectorySuffix; + if (screenshotSuffix.empty()) + screenshotSuffix = branding.getValue("appShort", "Mana"); - if (!configScreenshotSuffix.empty()) + if (!screenshotSuffix.empty()) { - mScreenshotDir += "/" + configScreenshotSuffix; - config.setValue("screenshotDirectorySuffix", - configScreenshotSuffix); + mScreenshotDir += "/" + screenshotSuffix; + config.screenshotDirectorySuffix = screenshotSuffix; } } } @@ -1249,15 +1217,15 @@ void Client::accountLogin(LoginData *loginData) // TODO This is not the best place to save the config, but at least better // than the login gui window if (loginData->remember) - config.setValue("username", loginData->username); - config.setValue("remember", loginData->remember); + config.username = loginData->username; + config.remember = loginData->remember; } void Client::handleWindowSizeChanged(int width, int height) { // Store the new size in the configuration. - config.setValue("screenwidth", width); - config.setValue("screenheight", height); + config.screenWidth = width; + config.screenHeight = height; mVideo.windowSizeChanged(width, height); diff --git a/src/client.h b/src/client.h index a2371a1c..e7127ddc 100644 --- a/src/client.h +++ b/src/client.h @@ -22,7 +22,6 @@ #ifndef CLIENT_H #define CLIENT_H -#include "eventlistener.h" #include "video.h" #include "net/serverinfo.h" @@ -111,7 +110,7 @@ public: * The core part of the client. This class initializes all subsystems, runs * the event loop, and shuts everything down again. */ -class Client final : public EventListener, public gcn::ActionListener +class Client final : public gcn::ActionListener { public: /** @@ -187,7 +186,6 @@ public: static Video &getVideo() { return instance()->mVideo; } - void event(Event::Channel channel, const Event &event) override; void action(const gcn::ActionEvent &event) override; /** @@ -239,7 +237,6 @@ private: SDL_TimerID mSecondsCounterId = 0; - int mFpsLimit = 0; FpsManager mFpsManager; }; diff --git a/src/commandhandler.cpp b/src/commandhandler.cpp index 9100c9e3..75cca1ab 100644 --- a/src/commandhandler.cpp +++ b/src/commandhandler.cpp @@ -23,6 +23,7 @@ #include "actorspritemanager.h" #include "channelmanager.h" +#include "configuration.h" #include "game.h" #include "localplayer.h" #include "playerrelations.h" @@ -36,6 +37,12 @@ #include "utils/gettext.h" #include "utils/stringutils.h" +std::string booleanOptionInstructions(const char *command) +{ + return strprintf(_("Options to /%s are \"yes\", \"no\", \"true\", \"false\", \"1\", \"0\"."), + command); +} + CommandHandler::CommandHandler() {} @@ -452,8 +459,8 @@ void CommandHandler::handleToggle(const std::string &args, ChatTab *tab) { if (args.empty()) { - tab->chatLog(chatWindow->getReturnTogglesChat() ? - _("Return toggles chat.") : _("Message closes chat.")); + tab->chatLog(config.returnTogglesChat ? _("Return toggles chat.") + : _("Message closes chat.")); return; } @@ -463,14 +470,14 @@ void CommandHandler::handleToggle(const std::string &args, ChatTab *tab) { case 1: tab->chatLog(_("Return now toggles chat.")); - chatWindow->setReturnTogglesChat(true); + config.returnTogglesChat = true; return; case 0: tab->chatLog(_("Message now closes chat.")); - chatWindow->setReturnTogglesChat(false); + config.returnTogglesChat = false; return; case -1: - tab->chatLog(strprintf(BOOLEAN_OPTIONS, "toggle")); + tab->chatLog(booleanOptionInstructions("toggle")); } } @@ -496,7 +503,7 @@ void CommandHandler::handleShowIp(const std::string &args, ChatTab *tab) local_player->setShowIp(true); break; case -1: - tab->chatLog(strprintf(BOOLEAN_OPTIONS, "showip")); + tab->chatLog(booleanOptionInstructions("showip")); return; } diff --git a/src/commandhandler.h b/src/commandhandler.h index 2bf670c1..42f68b2f 100644 --- a/src/commandhandler.h +++ b/src/commandhandler.h @@ -28,8 +28,7 @@ class ChatTab; extern ChatTab *localChatTab; -#define BOOLEAN_OPTIONS _("Options to /%s are \"yes\", \"no\", \"true\", "\ -"\"false\", \"1\", \"0\".") +std::string booleanOptionInstructions(const char *command); /** * A class to parse and handle user commands diff --git a/src/configuration.cpp b/src/configuration.cpp index 5fc4eabd..ead228c4 100644 --- a/src/configuration.cpp +++ b/src/configuration.cpp @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -33,16 +33,6 @@ void ConfigurationObject::setValue(const std::string &key, mOptions[key] = value; } -void Configuration::setValue(const std::string &key, const std::string &value) -{ - ConfigurationObject::setValue(key, value); - - // Notify listeners - Event event(Event::ConfigOptionChanged); - event.setString("option", key); - event.trigger(Event::ConfigChannel); -} - std::string ConfigurationObject::getValue(const std::string &key, const std::string &deflt) const { @@ -70,19 +60,8 @@ double ConfigurationObject::getValue(const std::string &key, return iter != mOptions.end() ? atof(iter->second.c_str()) : deflt; } -void ConfigurationObject::deleteList(std::list<ConfigurationObject*> &list) -{ - for (auto element : list) - delete element; - - list.clear(); -} - void ConfigurationObject::clear() { - for (auto &[_, list] : mContainerOptions) - deleteList(list); - mOptions.clear(); } @@ -212,33 +191,13 @@ void ConfigurationObject::initFromXML(XML::Node parent_node) for (auto node : parent_node.children()) { - if (node.name() == "list") + if (node.name() == "option") { - // List option handling. std::string name = node.getProperty("name", std::string()); - for (auto subnode : node.children()) - { - if (subnode.name() == name) - { - auto *cobj = new ConfigurationObject; - - cobj->initFromXML(subnode); // Recurse - - mContainerOptions[name].push_back(cobj); - } - } - - } - else if (node.name() == "option") - { - // Single option handling. - std::string name = node.getProperty("name", std::string()); - std::string value = node.getProperty("value", std::string()); - if (!name.empty()) - mOptions[name] = value; - } // Otherwise ignore + mOptions[name] = node.getProperty("value", std::string()); + } } } @@ -251,15 +210,15 @@ void Configuration::init(const std::string &filename, bool useResManager) else mConfigPath = filename; - if (!doc.rootNode()) + XML::Node rootNode = doc.rootNode(); + + if (!rootNode) { logger->log("Couldn't open configuration file: %s", filename.c_str()); return; } - XML::Node rootNode = doc.rootNode(); - - if (!rootNode || rootNode.name() != "configuration") + if (rootNode.name() != "configuration") { logger->log("Warning: No configuration file (%s)", filename.c_str()); return; @@ -268,57 +227,387 @@ void Configuration::init(const std::string &filename, bool useResManager) initFromXML(rootNode); } -void ConfigurationObject::writeToXML(XML::Writer &writer) const + +template<typename T> +struct Option +{ + Option(const char *name, const T &value, const T &defaultValue) + : name(name), value(value), defaultValue(defaultValue) + {} + + const char *name; + const T &value; + const T &defaultValue; +}; + +template<typename T> +static void serialize(XML::Writer &writer, const Option<T> &option) +{ + if (option.value == option.defaultValue) + return; + + writer.startElement("option"); + writer.addAttribute("name", option.name); + writer.addAttribute("value", option.value); + writer.endElement(); +} + +static void serialize(XML::Writer &writer, const ItemShortcutEntry &itemShortcut) +{ + writer.startElement("itemshortcut"); + writer.addAttribute("index", itemShortcut.index); + writer.addAttribute("id", itemShortcut.itemId); + writer.endElement(); +} + +static void serialize(XML::Writer &writer, const EmoteShortcutEntry &emoteShortcut) +{ + writer.startElement("emoteshortcut"); + writer.addAttribute("index", emoteShortcut.index); + writer.addAttribute("id", emoteShortcut.emoteId); + writer.endElement(); +} + +static void serialize(XML::Writer &writer, const Outfit &outfit) +{ + writer.startElement("outfit"); + writer.addAttribute("index", outfit.index); + writer.addAttribute("items", outfit.items); + writer.addAttribute("unequip", outfit.unequip); + writer.endElement(); +} + +static void serialize(XML::Writer &writer, const UserColor &color) +{ + if (!color.color.empty()) + writer.addAttribute("color", color.color); + + writer.addAttribute("gradient", color.gradient); + + if (color.delay) + writer.addAttribute("delay", *color.delay); +} + +static void serialize(XML::Writer &writer, const WindowState &state) { - for (auto &[name, value] : mOptions) + if (state.x) writer.addAttribute("x", *state.x); + if (state.y) writer.addAttribute("y", *state.y); + if (state.width) writer.addAttribute("width", *state.width); + if (state.height) writer.addAttribute("height", *state.height); + if (state.visible) writer.addAttribute("visible", *state.visible); + if (state.sticky) writer.addAttribute("sticky", *state.sticky); +} + +static const char *serverTypeToString(ServerType type) +{ + switch (type) { - writer.startElement("option"); - writer.addAttribute("name", name); - writer.addAttribute("value", value); - writer.endElement(); + case ServerType::TMWATHENA: + return "TmwAthena"; + case ServerType::MANASERV: + return "ManaServ"; + default: + return ""; } +} - for (auto &[name, list] : mContainerOptions) - { - writer.startElement("list"); - writer.addAttribute("name", name); +static void serialize(XML::Writer &writer, const ServerInfo &server) +{ + writer.startElement("server"); - // Recurse on all elements - for (auto element : list) - { - writer.startElement(name.c_str()); - element->writeToXML(writer); - writer.endElement(); - } + writer.addAttribute("name", server.name); + writer.addAttribute("type", serverTypeToString(server.type)); + + writer.startElement("connection"); + writer.addAttribute("hostname", server.hostname); + writer.addAttribute("port", server.port); + writer.endElement(); // connection + + if (!server.description.empty()) + { + writer.startElement("description"); + writer.writeText(server.description); + writer.endElement(); + } + if (!server.persistentIp) + { + writer.startElement("persistentIp"); + writer.writeText(server.persistentIp ? "1" : "0"); writer.endElement(); } + + writer.endElement(); // server +} + +template<typename T> +void serdeOptions(T option) +{ + option("OverlayDetail", &Config::overlayDetail); + option("speechBubblecolor", &Config::speechBubblecolor); + option("speechBubbleAlpha", &Config::speechBubbleAlpha); + option("speech", &Config::speech); + option("visiblenames", &Config::visibleNames); + option("showgender", &Config::showGender); + option("showMonstersTakedDamage", &Config::showMonstersTakedDamage); + option("showWarps", &Config::showWarps); + option("particleMaxCount", &Config::particleMaxCount); + option("particleFastPhysics", &Config::particleFastPhysics); + option("particleEmitterSkip", &Config::particleEmitterSkip); + option("particleeffects", &Config::particleEffects); + option("logToStandardOut", &Config::logToStandardOut); + option("opengl", &Config::opengl); + option("vsync", &Config::vsync); + option("windowmode", &Config::windowMode); + option("screenwidth", &Config::screenWidth); + option("screenheight", &Config::screenHeight); + option("scale", &Config::scale); + option("sound", &Config::sound); + option("sfxVolume", &Config::sfxVolume); + option("notificationsVolume", &Config::notificationsVolume); + option("musicVolume", &Config::musicVolume); + option("fpslimit", &Config::fpsLimit); + + option("remember", &Config::remember); + option("username", &Config::username); + option("lastCharacter", &Config::lastCharacter); + option("updatehost", &Config::updatehost); + option("screenshotDirectory", &Config::screenshotDirectory); + option("screenshotDirectorySuffix", &Config::screenshotDirectorySuffix); + option("useScreenshotDirectorySuffix", &Config::useScreenshotDirectorySuffix); + + option("EnableSync", &Config::enableSync); + + option("joystickEnabled", &Config::joystickEnabled); + option("upTolerance", &Config::upTolerance); + option("downTolerance", &Config::downTolerance); + option("leftTolerance", &Config::leftTolerance); + option("rightTolerance", &Config::rightTolerance); + + option("logNpcInGui", &Config::logNpcInGui); + option("download-music", &Config::downloadMusic); + option("guialpha", &Config::guiAlpha); + option("ChatLogLength", &Config::chatLogLength); + option("enableChatLog", &Config::enableChatLog); + option("whispertab", &Config::whisperTab); + option("customcursor", &Config::customCursor); + option("showownname", &Config::showOwnName); + option("showpickupparticle", &Config::showPickupParticle); + option("showpickupchat", &Config::showPickupChat); + option("showMinimap", &Config::showMinimap); + option("fontSize", &Config::fontSize); + option("ReturnToggles", &Config::returnTogglesChat); + option("ScrollLaziness", &Config::scrollLaziness); + option("ScrollRadius", &Config::scrollRadius); + option("ScrollCenterOffsetX", &Config::scrollCenterOffsetX); + option("ScrollCenterOffsetY", &Config::scrollCenterOffsetY); + option("onlineServerList", &Config::onlineServerList); + option("theme", &Config::theme); + option("disableTransparency", &Config::disableTransparency); + + option("persistent-player-list", &Config::persistentPlayerList); + option("player-ignore-strategy", &Config::playerIgnoreStrategy); + option("default-player-permissions", &Config::defaultPlayerPermissions); } -void Configuration::write() +void serialize(XML::Writer &writer, const Config &config) { - // Do not attempt to write to file that cannot be opened for writing - FILE *testFile = fopen(mConfigPath.c_str(), "w"); - if (!testFile) + const Config defaults; + auto serializeOption = [&](const char *name, auto member) { + serialize(writer, Option { name, config.*member, defaults.*member }); + }; + + writer.startElement("configuration"); + + serdeOptions(serializeOption); + + for (const auto &[name, value] : config.unknownOptions) + serialize(writer, Option { name.c_str(), value, std::string() }); + + for (const auto &[action, key] : config.keys) { - logger->log("Configuration::write() couldn't open %s for writing", - mConfigPath.c_str()); - return; + writer.startElement("key"); + writer.addAttribute("action", action); + writer.addAttribute("key", key); + writer.endElement(); } - fclose(testFile); + for (auto &itemShortcut : config.itemShortcuts) + serialize(writer, itemShortcut); + for (auto &emoteShortcut : config.emoteShortcuts) + serialize(writer, emoteShortcut); - XML::Writer writer(mConfigPath); + for (auto &outfit : config.outfits) + serialize(writer, outfit); - if (!writer.isValid()) + for (auto &[type, color] : config.colors) { - logger->log("Configuration::write() error while creating writer"); - return; + writer.startElement("color"); + writer.addAttribute("type", type); + + serialize(writer, color); + + writer.endElement(); } - logger->log("Configuration::write() writing configuration..."); + for (const auto &[name, state] : config.windows) + { + writer.startElement("window"); + writer.addAttribute("name", name); - writer.startElement("configuration"); - writeToXML(writer); + serialize(writer, state); + + writer.endElement(); // window + } + + for (const auto &server : config.servers) + { + if (server.save && server.isValid()) + serialize(writer, server); + } + + for (const auto &[name, relation] : config.players) + { + writer.startElement("player"); + writer.addAttribute("name", name); + writer.addAttribute("relation", static_cast<int>(relation)); + writer.endElement(); + } + + writer.endElement(); // configuration +} + +void deserialize(XML::Node node, ItemShortcutEntry &itemShortcut) +{ + node.attribute("index", itemShortcut.index); + node.attribute("id", itemShortcut.itemId); +} + +void deserialize(XML::Node node, EmoteShortcutEntry &emoteShortcut) +{ + node.attribute("index", emoteShortcut.index); + node.attribute("id", emoteShortcut.emoteId); +} + +void deserialize(XML::Node node, Outfit &outfit) +{ + node.attribute("index", outfit.index); + node.attribute("items", outfit.items); + node.attribute("unequip", outfit.unequip); +} + +void deserialize(XML::Node node, UserColor &color) +{ + node.attribute("color", color.color); + node.attribute("gradient", color.gradient); + node.attribute("delay", color.delay); +} + +void deserialize(XML::Node node, WindowState &state) +{ + node.attribute("x", state.x); + node.attribute("y", state.y); + node.attribute("width", state.width); + node.attribute("height", state.height); + node.attribute("visible", state.visible); + node.attribute("sticky", state.sticky); +} + +void deserialize(XML::Node node, ServerInfo &server) +{ + node.attribute("name", server.name); + + std::string type; + node.attribute("type", type); + server.type = ServerInfo::parseType(type); + + for (auto node : node.children()) { + if (node.name() == "connection") { + node.attribute("hostname", server.hostname); + node.attribute("port", server.port); + } else if (node.name() == "description") { + server.description = node.textContent(); + } else if (node.name() == "persistentIp") { + const std::string value { node.textContent() }; + server.persistentIp = getBoolFromString(value, server.persistentIp); + } + } +} + +void deserialize(XML::Node node, Config &config) +{ + std::map<std::string, std::string> options; + + for (auto node : node.children()) { + if (node.name() == "option") { + std::string name; + if (!node.attribute("name", name)) + continue; + node.attribute("value", options[name]); + } else if (node.name() == "list") { + // Backwards compatibility for old configuration files + for (auto node : node.children()) { + if (node.name() == "player") { + std::string playerName; + PlayerRelation relation = PlayerRelation::NEUTRAL; + + for (auto node : node.children()) { + if (node.name() == "option") { + std::string optionName; + + if (node.attribute("name", optionName)) { + if (optionName == "name") + node.attribute("value", playerName); + else if (optionName == "relation") + node.attribute("value", relation); + } + } + } + + if (!playerName.empty()) + config.players[playerName] = relation; + } + } + } else if (node.name() == "key") { + std::string action; + node.attribute("action", action); + if (!action.empty()) + node.attribute("key", config.keys[action]); + } else if (node.name() == "itemshortcut") { + deserialize(node, config.itemShortcuts.emplace_back()); + } else if (node.name() == "emoteshortcut") { + deserialize(node, config.emoteShortcuts.emplace_back()); + } else if (node.name() == "outfit") { + deserialize(node, config.outfits.emplace_back()); + } else if (node.name() == "color") { + std::string type; + node.attribute("type", type); + deserialize(node, config.colors[type]); + } else if (node.name() == "window") { + std::string name; + node.attribute("name", name); + deserialize(node, config.windows[name]); + } else if (node.name() == "player") { + std::string name; + node.attribute("name", name); + if (!name.empty()) + node.attribute("relation", config.players[name]); + } else if (node.name() == "server") { + deserialize(node, config.servers.emplace_back()); + } + } + + auto deserializeOption = [&](const char *name, auto member) { + auto it = options.find(name); + if (it == options.end()) + return; + + fromString(it->second.data(), config.*member); + options.erase(it); + }; + + serdeOptions(deserializeOption); + + config.unknownOptions = std::move(options); } diff --git a/src/configuration.h b/src/configuration.h index c6c115f6..69a211be 100644 --- a/src/configuration.h +++ b/src/configuration.h @@ -1,7 +1,7 @@ /* * The Mana Client * Copyright (C) 2004-2009 The Mana World Development Team - * Copyright (C) 2009-2012 The Mana Developers + * Copyright (C) 2009-2024 The Mana Developers * * This file is part of The Mana Client. * @@ -22,51 +22,20 @@ #ifndef CONFIGURATION_H #define CONFIGURATION_H +#include "being.h" #include "defaults.h" +#include "playerrelations.h" +#include "video.h" -#include "utils/stringutils.h" #include "utils/xml.h" +#include "net/serverinfo.h" + #include <cassert> -#include <list> #include <map> +#include <optional> #include <string> - -class ConfigurationObject; - -/** - * Configuration list manager interface; responsible for - * serializing/deserializing configuration choices in containers. - * - * \param T Type of the container elements to serialise - * \param CONT Type of the container we (de)serialise - */ -template <class T, class CONT> -class ConfigurationListManager -{ - public: - /** - * Writes a value into a configuration object - * - * \param value The value to write out - * \param obj The configuation object to write to - * \return obj, or otherwise NULL to indicate that this option should - * be skipped - */ - virtual ConfigurationObject *writeConfigItem(const T &value, - ConfigurationObject *obj) = 0; - - /** - * Reads a value from a configuration object - * - * \param obj The configuration object to read from - * \param container The container to insert the object to - */ - virtual CONT readConfigItem(ConfigurationObject *obj, - CONT container) = 0; - - virtual ~ConfigurationListManager() = default; -}; +#include <vector> /** * Configuration object, mapping values to names and possibly containing @@ -87,8 +56,7 @@ class ConfigurationObject * \param key Option identifier. * \param value Value. */ - virtual void setValue(const std::string &key, - const std::string &value); + void setValue(const std::string &key, const std::string &value); /** * Gets a value as string. @@ -110,74 +78,10 @@ class ConfigurationObject */ void clear(); - /** - * Serialises a container into a list of configuration options - * - * \tparam IT Iterator type over CONT - * \tparam T Elements that IT iterates over - * \tparam CONT The associated container type - * - * \param name Name of the list the elements should be stored under - * \param begin Iterator start - * \param end Iterator end - * \param manager An object capable of serialising T items - */ - template <class IT, class T, class CONT> - void setList(const std::string &name, IT begin, IT end, - ConfigurationListManager<T, CONT> &manager) - { - auto *nextobj = new ConfigurationObject; - std::list<ConfigurationObject *> &list = mContainerOptions[name]; - deleteList(list); - - for (IT it = begin; it != end; it++) - { - ConfigurationObject *wrobj = manager.writeConfigItem(*it, nextobj); - if (wrobj) - { // wrote something - assert (wrobj == nextobj); - nextobj = new ConfigurationObject; - list.push_back(wrobj); - } - else - { - nextobj->clear(); // you never know... - } - } - - delete nextobj; - } - - /** - * Serialises a container into a list of configuration options - * - * \tparam IT Iterator type over CONT - * \tparam T Elements that IT iterates over - * \tparam CONT The associated container type - * - * \param name Name of the list the elements should be read from under - * \param empty Initial (empty) container to write to - * \param manager An object capable of deserialising items into CONT - */ - template<class T, class CONT> - CONT getList(const std::string &name, CONT empty, ConfigurationListManager<T, CONT> &manager) - { - CONT container = empty; - - for (auto obj : mContainerOptions[name]) - container = manager.readConfigItem(obj, container); - - return container; - } - protected: void initFromXML(XML::Node node); - void writeToXML(XML::Writer &writer) const; - - void deleteList(std::list<ConfigurationObject *> &list); std::map<std::string, std::string> mOptions; - std::map<std::string, std::list<ConfigurationObject *>> mContainerOptions; }; /** @@ -208,31 +112,6 @@ class Configuration : public ConfigurationObject void setDefaultValues(DefaultsData *defaultsData); /** - * Writes the current settings back to the config file. - */ - void write(); - - void setValue(const std::string &key, const std::string &value) override; - - void setValue(const std::string &key, const char *value) - { setValue(key, std::string(value)); } - - void setValue(const std::string &key, float value) - { setValue(key, toString(value)); } - - void setValue(const std::string &key, double value) - { setValue(key, toString(value)); } - - void setValue(const std::string &key, int value) - { setValue(key, toString(value)); } - - void setValue(const std::string &key, unsigned value) - { setValue(key, toString(value)); } - - void setValue(const std::string &key, bool value) - { setValue(key, value ? "1" : "0"); } - - /** * returns a value corresponding to the given key. * The default value returned in based on fallbacks registry. * @see defaults.h @@ -257,8 +136,129 @@ class Configuration : public ConfigurationObject DefaultsData *mDefaultsData = nullptr; /**< Defaults of value for a given key */ }; +struct ItemShortcutEntry +{ + int index; + int itemId; +}; + +struct EmoteShortcutEntry +{ + int index; + int emoteId; +}; + +struct Outfit +{ + int index; + std::string items; + bool unequip; +}; + +struct UserColor +{ + std::string color; + int gradient; + std::optional<int> delay; +}; + +struct WindowState +{ + std::optional<int> x; + std::optional<int> y; + std::optional<int> width; + std::optional<int> height; + std::optional<bool> visible; + std::optional<bool> sticky; +}; + +struct Config +{ + int overlayDetail = 2; + std::string speechBubblecolor = "000000"; + float speechBubbleAlpha = 1.0f; + Being::Speech speech = Being::TEXT_OVERHEAD; + bool visibleNames = true; + bool showGender = false; + bool showMonstersTakedDamage = false; + bool showWarps = true; + int particleMaxCount = 3000; + int particleFastPhysics = 0; + int particleEmitterSkip = 1; + bool particleEffects = true; + bool logToStandardOut = false; + bool opengl = false; + bool vsync = true; + WindowMode windowMode = WindowMode::Windowed; + int screenWidth = defaultScreenWidth; + int screenHeight = defaultScreenHeight; + int scale = 0; + bool sound = true; + int sfxVolume = 100; + int notificationsVolume = 100; + int musicVolume = 60; + int fpsLimit = 0; + + bool remember = true; + std::string username; + std::string lastCharacter; + std::string updatehost; + std::string afkMessage; + std::string screenshotDirectory; + std::string screenshotDirectorySuffix; + bool useScreenshotDirectorySuffix = true; + + bool enableSync = false; + + bool joystickEnabled = false; + int upTolerance = 100; + int downTolerance = 100; + int leftTolerance = 100; + int rightTolerance = 100; + + bool logNpcInGui = true; + bool downloadMusic = false; + float guiAlpha = 0.8f; + int chatLogLength = 128; + bool enableChatLog = false; + bool whisperTab = true; + bool customCursor = true; + bool showOwnName = false; + bool showPickupParticle = true; + bool showPickupChat = false; + bool showMinimap = true; + int fontSize = 12; + bool returnTogglesChat = false; + int scrollLaziness = 16; + int scrollRadius = 0; + int scrollCenterOffsetX = 0; + int scrollCenterOffsetY = 0; + std::string onlineServerList; + std::string theme; + bool disableTransparency = false; + + bool persistentPlayerList = true; + std::string playerIgnoreStrategy = DEFAULT_IGNORE_STRATEGY; + unsigned defaultPlayerPermissions = PlayerPermissions::DEFAULT; + + std::map<std::string, std::string> keys; + std::vector<ItemShortcutEntry> itemShortcuts; + std::vector<EmoteShortcutEntry> emoteShortcuts; + std::vector<Outfit> outfits; + std::map<std::string, UserColor> colors; + std::map<std::string, WindowState> windows; + std::map<std::string, PlayerRelation> players; + ServerInfos servers; + + // For compatibility with old configuration files or different clients + std::map<std::string, std::string> unknownOptions; +}; + +void serialize(XML::Writer &writer, const Config &config); +void deserialize(XML::Node node, Config &config); + +extern Config config; extern Configuration branding; -extern Configuration config; extern Configuration paths; #endif diff --git a/src/defaults.cpp b/src/defaults.cpp index b17ba350..dff06bbb 100644 --- a/src/defaults.cpp +++ b/src/defaults.cpp @@ -20,7 +20,6 @@ #include "defaults.h" -#include "being.h" #include "client.h" VariableData *createData(int defData) @@ -59,70 +58,6 @@ void AddDEF(DefaultsData *defaultsData, const char *key, T value) defaultsData->insert(std::make_pair(key, createData(value))); } -DefaultsData* getConfigDefaults() -{ - auto* configData = new DefaultsData; - // Init main config defaults - AddDEF(configData, "OverlayDetail", 2); - AddDEF(configData, "speechBubblecolor", "000000"); - AddDEF(configData, "speechBubbleAlpha", 1.0f); - AddDEF(configData, "MostUsedServerName0", "server.themanaworld.org"); - AddDEF(configData, "visiblenames", true); - AddDEF(configData, "speech", Being::TEXT_OVERHEAD); - AddDEF(configData, "showgender", false); - AddDEF(configData, "showMonstersTakedDamage", false); - AddDEF(configData, "particleMaxCount", 3000); - AddDEF(configData, "particleFastPhysics", 0); - AddDEF(configData, "particleEmitterSkip", 1); - AddDEF(configData, "particleeffects", true); - AddDEF(configData, "logToStandardOut", false); - AddDEF(configData, "opengl", false); - AddDEF(configData, "windowmode", static_cast<int>(WindowMode::Windowed)); - AddDEF(configData, "screenwidth", defaultScreenWidth); - AddDEF(configData, "screenheight", defaultScreenHeight); - AddDEF(configData, "scale", 0); - AddDEF(configData, "vsync", true); - AddDEF(configData, "sound", true); - AddDEF(configData, "sfxVolume", 100); - AddDEF(configData, "notificationsVolume", 100); - AddDEF(configData, "musicVolume", 60); - AddDEF(configData, "remember", true); - AddDEF(configData, "username", ""); - AddDEF(configData, "lastCharacter", ""); - AddDEF(configData, "fpslimit", 0); - AddDEF(configData, "updatehost", ""); - AddDEF(configData, "screenshotDirectory", ""); - AddDEF(configData, "useScreenshotDirectorySuffix", true); - AddDEF(configData, "screenshotDirectorySuffix", ""); - AddDEF(configData, "EnableSync", false); - AddDEF(configData, "joystickEnabled", false); - AddDEF(configData, "upTolerance", 100); - AddDEF(configData, "downTolerance", 100); - AddDEF(configData, "leftTolerance", 100); - AddDEF(configData, "rightTolerance", 100); - AddDEF(configData, "logNpcInGui", true); - AddDEF(configData, "download-music", false); - AddDEF(configData, "guialpha", 0.8f); - AddDEF(configData, "ChatLogLength", 128); - AddDEF(configData, "enableChatLog", false); - AddDEF(configData, "whispertab", true); - AddDEF(configData, "customcursor", true); - AddDEF(configData, "showownname", false); - AddDEF(configData, "showpickupparticle", true); - AddDEF(configData, "showpickupchat", false); - AddDEF(configData, "fontSize", 12); - AddDEF(configData, "ReturnToggles", false); - AddDEF(configData, "ScrollLaziness", 16); - AddDEF(configData, "ScrollRadius", 0); - AddDEF(configData, "ScrollCenterOffsetX", 0); - AddDEF(configData, "ScrollCenterOffsetY", 0); - AddDEF(configData, "onlineServerList", ""); - AddDEF(configData, "theme", ""); - AddDEF(configData, "disableTransparency", false); - - return configData; -} - DefaultsData* getBrandingDefaults() { auto *brandingData = new DefaultsData; diff --git a/src/defaults.h b/src/defaults.h index a9532459..a588a543 100644 --- a/src/defaults.h +++ b/src/defaults.h @@ -27,7 +27,6 @@ using DefaultsData = std::map<std::string, VariableData *>; -DefaultsData* getConfigDefaults(); DefaultsData* getBrandingDefaults(); DefaultsData* getPathsDefaults(); diff --git a/src/emoteshortcut.cpp b/src/emoteshortcut.cpp index 69692437..cd80dea6 100644 --- a/src/emoteshortcut.cpp +++ b/src/emoteshortcut.cpp @@ -24,8 +24,6 @@ #include "configuration.h" #include "localplayer.h" -#include "utils/stringutils.h" - EmoteShortcut *emoteShortcut; EmoteShortcut::EmoteShortcut() @@ -41,16 +39,23 @@ EmoteShortcut::~EmoteShortcut() void EmoteShortcut::load() { for (int i = 0; i < SHORTCUT_EMOTES; i++) + mEmotes[i] = i + 1; + + for (auto &shortcut : config.emoteShortcuts) { - mEmotes[i] = (int) config.getValue("emoteshortcut" + toString(i), i + 1); + if (shortcut.index >= 0 && shortcut.index < SHORTCUT_EMOTES) + mEmotes[shortcut.index] = shortcut.emoteId; } } void EmoteShortcut::save() { + config.emoteShortcuts.clear(); + for (int i = 0; i < SHORTCUT_EMOTES; i++) { - config.setValue("emoteshortcut" + toString(i), mEmotes[i]); + if (mEmotes[i] != i + 1) + config.emoteShortcuts.push_back({ i, mEmotes[i] }); } } diff --git a/src/event.h b/src/event.h index 868aabab..9867c8aa 100644 --- a/src/event.h +++ b/src/event.h @@ -64,7 +64,7 @@ public: Close, CloseAll, CloseDialog, - ConfigOptionChanged, + ConfigOptionChanged, // todo: replace with more specific events Constructed, LoadingDatabases, Destroyed, diff --git a/src/game.cpp b/src/game.cpp index 96935981..c8b295bb 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -415,7 +415,7 @@ void Game::handleInput() if (setupWindow->isVisible() && keyboard.getNewKeyIndex() > KeyboardConfig::KEY_NO_VALUE) { - keyboard.setNewKey((int) event.key.keysym.sym); + keyboard.setNewKey(event.key.keysym.sym); keyboard.callbackNewKey(); keyboard.setNewKeyIndex(KeyboardConfig::KEY_NO_VALUE); return; diff --git a/src/gui/chatwindow.cpp b/src/gui/chatwindow.cpp index b4b03450..453baea2 100644 --- a/src/gui/chatwindow.cpp +++ b/src/gui/chatwindow.cpp @@ -123,14 +123,11 @@ ChatWindow::ChatWindow(): mChatInput->setHistory(mHistory); mChatInput->setAutoComplete(mAutoComplete); - mReturnToggles = config.getBoolValue("ReturnToggles"); - mRecorder = new Recorder(this); } ChatWindow::~ChatWindow() { - config.setValue("ReturnToggles", mReturnToggles); delete mRecorder; removeAllWhispers(); delete mItemLinkHandler; @@ -197,7 +194,7 @@ void ChatWindow::action(const gcn::ActionEvent &event) mChatInput->setText(std::string()); } - if (message.empty() || !mReturnToggles) + if (message.empty() || !config.returnTogglesChat) { // Remove focus and hide input mFocusHandler->focusNone(); @@ -469,7 +466,7 @@ void ChatWindow::whisper(const std::string &nick, if (i != mWhispers.end()) tab = i->second; - else if (config.getBoolValue("whispertab")) + else if (config.whisperTab) tab = addWhisperTab(nick); if (tab) diff --git a/src/gui/chatwindow.h b/src/gui/chatwindow.h index 9b46d7ad..59ab6d99 100644 --- a/src/gui/chatwindow.h +++ b/src/gui/chatwindow.h @@ -152,10 +152,10 @@ class ChatWindow : public Window, /** Override to reset mTmpVisible */ void setVisible(bool visible) override; - void mousePressed(gcn::MouseEvent &event) override; - void mouseDragged(gcn::MouseEvent &event) override; + void mousePressed(gcn::MouseEvent &event) override; + void mouseDragged(gcn::MouseEvent &event) override; - void event(Event::Channel channel, const Event &event) override; + void event(Event::Channel channel, const Event &event) override; /** * Scrolls the chat window @@ -173,9 +173,6 @@ class ChatWindow : public Window, */ void setRecordingFile(const std::string &msg); - bool getReturnTogglesChat() const { return mReturnToggles; } - void setReturnTogglesChat(bool toggles) { mReturnToggles = toggles; } - void doPresent(); void whisper(const std::string &nick, const std::string &mes, @@ -216,9 +213,6 @@ class ChatWindow : public Window, /** Manage whisper tabs */ std::map<const std::string, ChatTab *> mWhispers; - - bool mReturnToggles; /**< Marks whether <Return> toggles the chat log - or not */ }; extern ChatWindow *chatWindow; diff --git a/src/gui/customserverdialog.cpp b/src/gui/customserverdialog.cpp index c4fadca9..c7c03b1a 100644 --- a/src/gui/customserverdialog.cpp +++ b/src/gui/customserverdialog.cpp @@ -20,8 +20,6 @@ #include "gui/customserverdialog.h" -#include "configuration.h" - #include "gui/okdialog.h" #include "gui/sdlinput.h" #include "gui/serverdialog.h" diff --git a/src/gui/customserverdialog.h b/src/gui/customserverdialog.h index 59c1d2cc..8b0af4c8 100644 --- a/src/gui/customserverdialog.h +++ b/src/gui/customserverdialog.h @@ -30,8 +30,6 @@ class TypeListModel; #include "gui/widgets/window.h" -#include "net/serverinfo.h" - #include <guichan/actionlistener.hpp> #include <guichan/keylistener.hpp> #include <guichan/listmodel.hpp> diff --git a/src/gui/emotepopup.cpp b/src/gui/emotepopup.cpp index 8a85aca3..589d5087 100644 --- a/src/gui/emotepopup.cpp +++ b/src/gui/emotepopup.cpp @@ -22,10 +22,10 @@ #include "gui/emotepopup.h" -#include "imagesprite.h" #include "configuration.h" #include "emoteshortcut.h" #include "graphics.h" +#include "imagesprite.h" #include "log.h" #include "resources/emotedb.h" @@ -46,7 +46,7 @@ EmotePopup::EmotePopup() if (!mSelectionImage) logger->error("Unable to load selection.png"); - mSelectionImage->setAlpha(config.getFloatValue("guialpha")); + mSelectionImage->setAlpha(config.guiAlpha); addMouseListener(this); recalculateSize(); diff --git a/src/gui/gui.cpp b/src/gui/gui.cpp index 2ff697c7..39314fcf 100644 --- a/src/gui/gui.cpp +++ b/src/gui/gui.cpp @@ -81,7 +81,7 @@ Gui::Gui(Graphics *graphics) ResourceManager *resman = ResourceManager::getInstance(); // Set global font - const int fontSize = config.getValue("fontSize", 11); + const int fontSize = config.fontSize; std::string fontFile = branding.getValue("font", "fonts/dejavusans.ttf"); std::string path = resman->getPath(fontFile); @@ -131,7 +131,7 @@ Gui::Gui(Graphics *graphics) gcn::Widget::setGlobalFont(mGuiFont); // Initialize mouse cursor and listen for changes to the option - setUseCustomCursor(config.getBoolValue("customcursor")); + setUseCustomCursor(config.customCursor); listen(Event::ConfigChannel); } @@ -179,7 +179,7 @@ void Gui::event(Event::Channel channel, const Event &event) if (event.getType() == Event::ConfigOptionChanged && event.getString("option") == "customcursor") { - setUseCustomCursor(config.getBoolValue("customcursor")); + setUseCustomCursor(config.customCursor); } } } diff --git a/src/gui/minimap.cpp b/src/gui/minimap.cpp index cb38fba6..f5206eda 100644 --- a/src/gui/minimap.cpp +++ b/src/gui/minimap.cpp @@ -26,7 +26,6 @@ #include "configuration.h" #include "graphics.h" #include "localplayer.h" -#include "log.h" #include "map.h" #include "gui/setup.h" @@ -39,13 +38,10 @@ #include <guichan/font.hpp> -bool Minimap::mShow = true; - Minimap::Minimap(): Window(_("Map")) { setWindowName("Minimap"); - mShow = config.getValue(getWindowName() + "Show", true); setDefaultSize(5, 25, 100, 100); // set this to false as the minimap window size is changed //depending on the map size @@ -59,13 +55,11 @@ Minimap::Minimap(): setSticky(false); loadWindowState(); - setVisible(mShow, isSticky()); + setVisible(config.showMinimap, isSticky()); } Minimap::~Minimap() -{ - config.setValue(getWindowName() + "Show", mShow); -} +{} void Minimap::setMap(Map *map) { @@ -122,7 +116,7 @@ void Minimap::setMap(Map *map) setDefaultSize(getX(), getY(), getWidth(), getHeight()); resetToDefaultSize(); - if (mShow) + if (config.showMinimap) setVisible(true); } else @@ -135,7 +129,7 @@ void Minimap::setMap(Map *map) void Minimap::toggle() { setVisible(!isVisible(), isSticky()); - mShow = isVisible(); + config.showMinimap = isVisible(); } void Minimap::draw(gcn::Graphics *graphics) diff --git a/src/gui/minimap.h b/src/gui/minimap.h index 6e80a3c1..8212f5b7 100644 --- a/src/gui/minimap.h +++ b/src/gui/minimap.h @@ -64,7 +64,6 @@ class Minimap : public Window ResourceRef<Image> mMapImage; float mWidthProportion = 0.5; float mHeightProportion = 0.5; - static bool mShow; }; extern Minimap *minimap; diff --git a/src/gui/ministatuswindow.cpp b/src/gui/ministatuswindow.cpp index e22172bc..598cb722 100644 --- a/src/gui/ministatuswindow.cpp +++ b/src/gui/ministatuswindow.cpp @@ -86,7 +86,9 @@ MiniStatusWindow::MiniStatusWindow(): setContentSize(mXpBar->getX() + mXpBar->getWidth(), mXpBar->getY() + mXpBar->getHeight()); - setVisible((bool) config.getValue(getPopupName() + "Visible", true)); + auto stateIt = config.windows.find(getPopupName()); + setVisible(stateIt != config.windows.end() ? stateIt->second.visible.value_or(true) + : true); mTextPopup = new TextPopup(); diff --git a/src/gui/npcdialog.cpp b/src/gui/npcdialog.cpp index 33b512f0..18b3ff1b 100644 --- a/src/gui/npcdialog.cpp +++ b/src/gui/npcdialog.cpp @@ -71,7 +71,6 @@ NpcDialog::DialogList NpcDialog::instances; NpcDialog::NpcDialog(int npcId) : Window(_("NPC")) , mNpcId(npcId) - , mLogInteraction(config.getBoolValue("logNpcInGui")) , mItemLinkHandler(std::make_unique<ItemLinkHandler>(this)) { // Basic Window Setup @@ -141,7 +140,6 @@ NpcDialog::NpcDialog(int npcId) setVisible(true); requestFocus(); - listen(Event::ConfigChannel); PlayerInfo::setNPCInteractionCount(PlayerInfo::getNPCInteractionCount() + 1); } @@ -175,7 +173,7 @@ void NpcDialog::setText(const std::vector<std::string> &text) void NpcDialog::addText(const std::string &text, bool save) { - if (save || mLogInteraction) + if (save || config.logNpcInGui) { mNewText.push_back(text); mTextBox->addRow(text); @@ -244,7 +242,7 @@ void NpcDialog::action(const gcn::ActionEvent &event) mNewText.clear(); } - if (!mLogInteraction) + if (!config.logNpcInGui) setText({}); } else if (event.getId() == "reset") @@ -378,18 +376,6 @@ void NpcDialog::setVisible(bool visible) } } -void NpcDialog::event(Event::Channel channel, const Event &event) -{ - if (channel != Event::ConfigChannel) - return; - - if (event.getType() == Event::ConfigOptionChanged && - event.getString("option") == "logNpcInGui") - { - mLogInteraction = config.getBoolValue("logNpcInGui"); - } -} - void NpcDialog::mouseClicked(gcn::MouseEvent &mouseEvent) { if (mouseEvent.getSource() == mItemList && @@ -457,7 +443,7 @@ void NpcDialog::buildLayout() } else if (mInputState != NPC_INPUT_NONE) { - if (!mLogInteraction) + if (!config.logNpcInGui) setText(mNewText); mNextButton->setCaption(CAPTION_SUBMIT); diff --git a/src/gui/npcdialog.h b/src/gui/npcdialog.h index 42485766..f2b50370 100644 --- a/src/gui/npcdialog.h +++ b/src/gui/npcdialog.h @@ -22,8 +22,6 @@ #ifndef NPCDIALOG_H #define NPCDIALOG_H -#include "eventlistener.h" - #include "gui/widgets/window.h" #include <guichan/actionlistener.hpp> @@ -48,8 +46,7 @@ class Button; */ class NpcDialog final : public Window, public gcn::ActionListener, - public gcn::ListModel, - public EventListener + public gcn::ListModel { public: NpcDialog(int npcId); @@ -143,8 +140,6 @@ class NpcDialog final : public Window, void setVisible(bool visible) override; - void event(Event::Channel channel, const Event &event) override; - void mouseClicked(gcn::MouseEvent &mouseEvent) override; /** @@ -170,7 +165,6 @@ class NpcDialog final : public Window, void buildLayout(); int mNpcId; - bool mLogInteraction; int mDefaultInt = 0; std::string mDefaultString; diff --git a/src/gui/outfitwindow.cpp b/src/gui/outfitwindow.cpp index 77de4b3a..b5033d70 100644 --- a/src/gui/outfitwindow.cpp +++ b/src/gui/outfitwindow.cpp @@ -50,8 +50,7 @@ OutfitWindow::OutfitWindow(): mNextButton = new Button(_(">"), "next", this); mCurrentLabel = new Label(strprintf(_("Outfit: %d"), 1)); mCurrentLabel->setAlignment(gcn::Graphics::CENTER); - mUnequipCheck = new CheckBox(_("Unequip first"), - config.getValue("OutfitUnequip0", true)); + mUnequipCheck = new CheckBox(_("Unequip first")); mUnequipCheck->setActionEventId("unequip"); mUnequipCheck->addActionListener(this); @@ -68,6 +67,8 @@ OutfitWindow::OutfitWindow(): loadWindowState(); load(); + + mUnequipCheck->setSelected(mOutfits[mCurrentOutfit].unequip); } OutfitWindow::~OutfitWindow() @@ -77,34 +78,48 @@ OutfitWindow::~OutfitWindow() void OutfitWindow::load() { - memset(mItems, -1, sizeof(mItems)); for (int o = 0; o < OUTFITS_COUNT; o++) + memset(mOutfits[o].items, -1, sizeof(mOutfits[o].items)); + + for (auto &outfit : config.outfits) { - std::string outfit = config.getValue("Outfit" + toString(o), "-1"); + if (outfit.index < 0 || outfit.index >= OUTFITS_COUNT) + continue; + std::string buf; - std::stringstream ss(outfit); + std::stringstream ss(outfit.items); for (size_t i = 0; (ss >> buf) && i < OUTFIT_ITEM_COUNT; i++) { - mItems[o][i] = atoi(buf.c_str()); + mOutfits[outfit.index].items[i] = atoi(buf.c_str()); } - mItemsUnequip[o] = config.getValue("OutfitUnequip" + toString(o), true); + mOutfits[outfit.index].unequip = outfit.unequip; } } void OutfitWindow::save() { + config.outfits.clear(); + std::string outfitStr; for (int o = 0; o < OUTFITS_COUNT; o++) { + auto &items = mOutfits[o].items; + bool emptyOutfit = true; + for (int i = 0; i < OUTFIT_ITEM_COUNT; i++) { - outfitStr += mItems[o][i] ? toString(mItems[o][i]) : toString(-1); - if (i <8) outfitStr += " "; + if (!outfitStr.empty()) + outfitStr += " "; + + outfitStr += items[i] ? toString(items[i]) : toString(-1); + emptyOutfit &= items[i] <= 0; } - config.setValue("Outfit" + toString(o), outfitStr); - config.setValue("OutfitUnequip" + toString(o), mItemsUnequip[o]); + + if (!emptyOutfit) + config.outfits.push_back({ o, outfitStr, mOutfits[o].unequip }); + outfitStr.clear(); } } @@ -118,7 +133,7 @@ void OutfitWindow::action(const gcn::ActionEvent &event) else mCurrentOutfit = 0; mCurrentLabel->setCaption(strprintf(_("Outfit: %d"), mCurrentOutfit + 1)); - mUnequipCheck->setSelected(mItemsUnequip[mCurrentOutfit]); + mUnequipCheck->setSelected(mOutfits[mCurrentOutfit].unequip); } else if (event.getId() == "previous") { @@ -131,23 +146,23 @@ void OutfitWindow::action(const gcn::ActionEvent &event) mCurrentOutfit = OUTFITS_COUNT - 1; } mCurrentLabel->setCaption(strprintf(_("Outfit: %d"), mCurrentOutfit + 1)); - mUnequipCheck->setSelected(mItemsUnequip[mCurrentOutfit]); + mUnequipCheck->setSelected(mOutfits[mCurrentOutfit].unequip); } else if (event.getId() == "unequip") { - mItemsUnequip[mCurrentOutfit] = mUnequipCheck->isSelected(); + mOutfits[mCurrentOutfit].unequip = mUnequipCheck->isSelected(); } } void OutfitWindow::wearOutfit(int outfit) { - if (mItemsUnequip[outfit]) + if (mOutfits[outfit].unequip) unequipNotInOutfit(outfit); Item *item; for (int i = 0; i < OUTFIT_ITEM_COUNT; i++) { - item = PlayerInfo::getInventory()->findItem(mItems[outfit][i]); + item = PlayerInfo::getInventory()->findItem(mOutfits[outfit].items[i]); if (item && !item->isEquipped() && item->getQuantity()) { if (item->isEquippable()) @@ -160,7 +175,7 @@ void OutfitWindow::copyOutfit(int outfit) { for (int i = 0; i < OUTFIT_ITEM_COUNT; i++) { - mItems[mCurrentOutfit][i] = mItems[outfit][i]; + mOutfits[mCurrentOutfit].items[i] = mOutfits[outfit].items[i]; } } @@ -183,15 +198,15 @@ void OutfitWindow::draw(gcn::Graphics *graphics) ITEM_ICON_SIZE, ITEM_ICON_SIZE)); - if (mItems[mCurrentOutfit][i] < 0) + if (mOutfits[mCurrentOutfit].items[i] < 0) { continue; } Item *item = - PlayerInfo::getInventory()->findItem(mItems[mCurrentOutfit][i]); + PlayerInfo::getInventory()->findItem(mOutfits[mCurrentOutfit].items[i]); if (item) - { + { // Draw item icon. if (Image *image = item->getImage()) { @@ -199,6 +214,7 @@ void OutfitWindow::draw(gcn::Graphics *graphics) } } } + if (mItemMoved) { // Draw the item image being dragged by the cursor. @@ -216,6 +232,7 @@ void OutfitWindow::draw(gcn::Graphics *graphics) void OutfitWindow::mouseDragged(gcn::MouseEvent &event) { Window::mouseDragged(event); + if (event.getButton() == gcn::MouseEvent::LEFT) { if (!mItemMoved && mItemClicked) @@ -223,16 +240,18 @@ void OutfitWindow::mouseDragged(gcn::MouseEvent &event) const int index = getIndexFromGrid(event.getX(), event.getY()); if (index == -1) return; - const int itemId = mItems[mCurrentOutfit][index]; + + const int itemId = mOutfits[mCurrentOutfit].items[index]; if (itemId < 0) return; - Item *item = PlayerInfo::getInventory()->findItem(itemId); - if (item) + + if (Item *item = PlayerInfo::getInventory()->findItem(itemId)) { mItemMoved = item; - mItems[mCurrentOutfit][index] = -1; + mOutfits[mCurrentOutfit].items[index] = -1; } } + if (mItemMoved) { mCursorPosX = event.getX(); @@ -251,10 +270,10 @@ void OutfitWindow::mousePressed(gcn::MouseEvent &event) // Stores the selected item if there is one. if (isItemSelected()) { - mItems[mCurrentOutfit][index] = mItemSelected; + mOutfits[mCurrentOutfit].items[index] = mItemSelected; mItemSelected = -1; } - else if (mItems[mCurrentOutfit][index]) + else if (mOutfits[mCurrentOutfit].items[index]) { mItemClicked = true; } @@ -277,7 +296,7 @@ void OutfitWindow::mouseReleased(gcn::MouseEvent &event) } if (mItemMoved) { - mItems[mCurrentOutfit][index] = mItemMoved->getId(); + mOutfits[mCurrentOutfit].items[index] = mItemMoved->getId(); mItemMoved = nullptr; } if (mItemClicked) @@ -311,7 +330,7 @@ void OutfitWindow::unequipNotInOutfit(int outfit) bool found = false; for (int f = 0; f < OUTFIT_ITEM_COUNT; f++) { - if (inventory->getItem(i)->getId() == mItems[outfit][f]) + if (inventory->getItem(i)->getId() == mOutfits[outfit].items[f]) { found = true; break; @@ -319,9 +338,7 @@ void OutfitWindow::unequipNotInOutfit(int outfit) } if (!found) { - Item *item = inventory->getItem(i); - - if (item) + if (Item *item = inventory->getItem(i)) item->doEvent(Event::DoUnequip); } } diff --git a/src/gui/outfitwindow.h b/src/gui/outfitwindow.h index aa07e020..56e96795 100644 --- a/src/gui/outfitwindow.h +++ b/src/gui/outfitwindow.h @@ -78,8 +78,13 @@ class OutfitWindow : public Window, gcn::ActionListener void save(); - int mItems[OUTFITS_COUNT][OUTFIT_ITEM_COUNT]; - bool mItemsUnequip[OUTFITS_COUNT]; + struct Outfit + { + int items[OUTFIT_ITEM_COUNT]; + bool unequip = true; + }; + + Outfit mOutfits[OUTFITS_COUNT]; int mItemSelected = -1; int mCurrentOutfit = 0; diff --git a/src/gui/palette.h b/src/gui/palette.h index b81d8865..9de911d5 100644 --- a/src/gui/palette.h +++ b/src/gui/palette.h @@ -33,7 +33,7 @@ #include <vector> // Default Gradient Delay -#define GRADIENT_DELAY 40 +constexpr int GRADIENT_DELAY = 40; /** * Class controlling the game's color palette. diff --git a/src/gui/serverdialog.cpp b/src/gui/serverdialog.cpp index bb978a78..01b477da 100644 --- a/src/gui/serverdialog.cpp +++ b/src/gui/serverdialog.cpp @@ -52,19 +52,6 @@ static const int MAX_SERVERLIST = 6; -static std::string serverTypeToString(ServerType type) -{ - switch (type) - { - case ServerType::TMWATHENA: - return "TmwAthena"; - case ServerType::MANASERV: - return "ManaServ"; - default: - return std::string(); - } -} - ServersListModel::ServersListModel(ServerInfos *servers, ServerDialog *parent): mServers(servers), mVersionStrings(servers->size(), VersionString(0, std::string())), @@ -413,7 +400,7 @@ void ServerDialog::downloadServerList() std::string listFile = branding.getStringValue("onlineServerList"); if (listFile.empty()) - listFile = config.getStringValue("onlineServerList"); + listFile = config.onlineServerList; // Fall back to manasource.org when neither branding nor config set it if (listFile.empty()) @@ -533,38 +520,18 @@ void ServerDialog::loadServers() void ServerDialog::loadCustomServers() { - for (int i = 0; i < MAX_SERVERLIST; ++i) + for (auto &server : config.servers) { - const std::string index = toString(i); - const std::string nameKey = "MostUsedServerDescName" + index; - const std::string hostNameKey = "MostUsedServerName" + index; - const std::string typeKey = "MostUsedServerType" + index; - const std::string portKey = "MostUsedServerPort" + index; - const std::string descriptionKey = "MostUsedServerDescription" + index; - - ServerInfo server; - server.name = config.getValue(nameKey, std::string()); - server.hostname = config.getValue(hostNameKey, std::string()); - server.type = ServerInfo::parseType(config.getValue(typeKey, std::string())); - - const uint16_t defaultPort = ServerInfo::defaultPortForServerType(server.type); - server.port = static_cast<uint16_t>(config.getValue(portKey, defaultPort)); - server.description = config.getValue(descriptionKey, std::string()); - - // Stop on the first invalid server - if (!server.isValid()) - break; - - server.save = true; - - mServers.push_back(server); + if (server.isValid()) + { + server.save = true; + mServers.push_back(server); + } } } void ServerDialog::saveCustomServers(const ServerInfo ¤tServer, int index) { - ServerInfos::iterator it, it_end = mServers.end(); - // Make sure the current server is mentioned first if (currentServer.isValid()) { @@ -574,7 +541,7 @@ void ServerDialog::saveCustomServers(const ServerInfo ¤tServer, int index) } else { - for (it = mServers.begin(); it != it_end; ++it) + for (auto it = mServers.begin(), it_end = mServers.end(); it != it_end; ++it) { if (*it == currentServer) { @@ -586,35 +553,7 @@ void ServerDialog::saveCustomServers(const ServerInfo ¤tServer, int index) } } - int savedServerCount = 0; - - for (it = mServers.begin(), it_end = mServers.end(); - it != it_end && savedServerCount < MAX_SERVERLIST; ++it) - { - const ServerInfo &server = *it; - - // Only save servers that were loaded from settings - if (!(server.save && server.isValid())) - continue; - - const std::string index = toString(savedServerCount); - const std::string nameKey = "MostUsedServerDescName" + index; - const std::string hostNameKey = "MostUsedServerName" + index; - const std::string typeKey = "MostUsedServerType" + index; - const std::string portKey = "MostUsedServerPort" + index; - const std::string descriptionKey = "MostUsedServerDescription" + index; - - config.setValue(hostNameKey, toString(server.hostname)); - config.setValue(typeKey, serverTypeToString(server.type)); - config.setValue(portKey, toString(server.port)); - config.setValue(nameKey, server.name); - config.setValue(descriptionKey, server.description); - ++savedServerCount; - } - - // Insert an invalid entry at the end to make the loading stop there - if (savedServerCount < MAX_SERVERLIST) - config.setValue("MostUsedServerName" + toString(savedServerCount), std::string()); + config.servers = mServers; // Restore the correct description if (index < 0) diff --git a/src/gui/setup_audio.cpp b/src/gui/setup_audio.cpp index 6d18e71f..f51bfcb6 100644 --- a/src/gui/setup_audio.cpp +++ b/src/gui/setup_audio.cpp @@ -34,11 +34,11 @@ #include "utils/gettext.h" Setup_Audio::Setup_Audio(): - mMusicVolume(config.getIntValue("musicVolume")), - mSfxVolume(config.getIntValue("sfxVolume")), - mNotificationsVolume(config.getIntValue("notificationsVolume")), - mSoundEnabled(config.getBoolValue("sound")), - mDownloadEnabled(config.getBoolValue("download-music")), + mMusicVolume(config.musicVolume), + mSfxVolume(config.sfxVolume), + mNotificationsVolume(config.notificationsVolume), + mSoundEnabled(config.sound), + mDownloadEnabled(config.downloadMusic), mSoundCheckBox(new CheckBox(_("Sound"), mSoundEnabled)), mDownloadMusicCheckBox(new CheckBox(_("Download music"), mDownloadEnabled)), mSfxSlider(new Slider(0, sound.getMaxVolume())), @@ -84,19 +84,19 @@ void Setup_Audio::apply() { mSoundEnabled = mSoundCheckBox->isSelected(); mDownloadEnabled = mDownloadMusicCheckBox->isSelected(); - mSfxVolume = config.getIntValue("sfxVolume"); - mNotificationsVolume = config.getIntValue("sfxVolume"); - mMusicVolume = config.getIntValue("musicVolume"); + mSfxVolume = config.sfxVolume; + mNotificationsVolume = config.sfxVolume; + mMusicVolume = config.musicVolume; - config.setValue("sound", mSoundEnabled); + config.sound = mSoundEnabled; // Display a message if user has selected to download music, // And if downloadmusic is not already enabled - if (mDownloadEnabled && !config.getBoolValue("download-music")) + if (mDownloadEnabled && !config.downloadMusic) { new OkDialog(_("Notice"),_("You may have to restart your client if you want to download new music")); } - config.setValue("download-music", mDownloadEnabled); + config.downloadMusic = mDownloadEnabled; if (mSoundEnabled) { @@ -127,10 +127,10 @@ void Setup_Audio::cancel() sound.setMusicVolume(mMusicVolume); mMusicSlider->setValue(mMusicVolume); - config.setValue("sound", mSoundEnabled); - config.setValue("download-music", mDownloadEnabled); - config.setValue("sfxVolume", mSfxVolume); - config.setValue("musicVolume", mMusicVolume); + config.sound = mSoundEnabled; + config.downloadMusic = mDownloadEnabled; + config.sfxVolume = mSfxVolume; + config.musicVolume = mMusicVolume; } void Setup_Audio::action(const gcn::ActionEvent &event) @@ -138,19 +138,19 @@ void Setup_Audio::action(const gcn::ActionEvent &event) if (event.getId() == "sfx") { int volume = (int) mSfxSlider->getValue(); - config.setValue("sfxVolume", volume); + config.sfxVolume = volume; sound.setSfxVolume(volume); } else if (event.getId() == "notifications") { int volume = (int) mNotificationsSlider->getValue(); - config.setValue("notificationsVolume", volume); + config.notificationsVolume = volume; sound.setNotificationsVolume(volume); } else if (event.getId() == "music") { int volume = (int) mMusicSlider->getValue(); - config.setValue("musicVolume", volume); + config.musicVolume = volume; sound.setMusicVolume(volume); } } diff --git a/src/gui/setup_interface.cpp b/src/gui/setup_interface.cpp index 3801861b..229898c7 100644 --- a/src/gui/setup_interface.cpp +++ b/src/gui/setup_interface.cpp @@ -77,14 +77,14 @@ static const char *speechModeToString(Being::Speech mode) } Setup_Interface::Setup_Interface(): - mShowMonsterDamageEnabled(config.getBoolValue("showMonstersTakedDamage")), - mVisibleNamesEnabled(config.getBoolValue("visiblenames")), - mNameEnabled(config.getBoolValue("showownname")), - mNPCLogEnabled(config.getBoolValue("logNpcInGui")), - mPickupChatEnabled(config.getBoolValue("showpickupchat")), - mPickupParticleEnabled(config.getBoolValue("showpickupparticle")), - mOpacity(config.getFloatValue("guialpha")), - mSpeechMode(static_cast<Being::Speech>(config.getIntValue("speech"))), + mShowMonsterDamageEnabled(config.showMonstersTakedDamage), + mVisibleNamesEnabled(config.visibleNames), + mNameEnabled(config.showOwnName), + mNPCLogEnabled(config.logNpcInGui), + mPickupChatEnabled(config.showPickupChat), + mPickupParticleEnabled(config.showPickupParticle), + mOpacity(config.guiAlpha), + mSpeechMode(config.speech), mVisibleNamesCheckBox(new CheckBox(_("Visible names"), mVisibleNamesEnabled)), mNameCheckBox(new CheckBox(_("Show own name"), mNameEnabled)), @@ -98,7 +98,7 @@ Setup_Interface::Setup_Interface(): mSpeechSlider(new Slider(0, 3)), mSpeechLabel(new Label(std::string())), mAlphaSlider(new Slider(0.2, 1.0)), - mFontSize(config.getIntValue("fontSize")) + mFontSize(config.fontSize) { setName(_("Interface")); @@ -117,7 +117,7 @@ Setup_Interface::Setup_Interface(): mAlphaSlider->setValue(mOpacity); mAlphaSlider->setWidth(90); - mAlphaSlider->setEnabled(!config.getBoolValue("disableTransparency")); + mAlphaSlider->setEnabled(!config.disableTransparency); // Set actions @@ -182,16 +182,16 @@ Setup_Interface::~Setup_Interface() void Setup_Interface::apply() { - config.setValue("fontSize", mFontSizeDropDown->getSelected() + 10); - - mShowMonsterDamageEnabled = config.getBoolValue("showMonstersTakedDamage"); - mVisibleNamesEnabled = config.getBoolValue("visiblenames"); - mNameEnabled = config.getBoolValue("showownname"); - mNPCLogEnabled = config.getBoolValue("logNpcInGui"); - mSpeechMode = static_cast<Being::Speech>(config.getIntValue("speech")); - mOpacity = config.getFloatValue("guialpha"); - mPickupChatEnabled = config.getBoolValue("showpickupchat"); - mPickupParticleEnabled = config.getBoolValue("showpickupparticle"); + config.fontSize = mFontSizeDropDown->getSelected() + 10; + + mShowMonsterDamageEnabled = config.showMonstersTakedDamage; + mVisibleNamesEnabled = config.visibleNames; + mNameEnabled = config.showOwnName; + mNPCLogEnabled = config.logNpcInGui; + mSpeechMode = config.speech; + mOpacity = config.guiAlpha; + mPickupChatEnabled = config.showPickupChat; + mPickupParticleEnabled = config.showPickupParticle; } void Setup_Interface::cancel() @@ -204,14 +204,14 @@ void Setup_Interface::cancel() mAlphaSlider->setValue(mOpacity); //mAlphaSlider->setEnabled(!mSDLTransparencyDisabled); - config.setValue("showMonstersTakedDamage", mShowMonsterDamageEnabled); - config.setValue("visiblenames", mVisibleNamesEnabled); - config.setValue("speech", mSpeechMode); - config.setValue("showownname", mNameEnabled); - config.setValue("logNpcInGui", mNPCLogEnabled); - config.setValue("guialpha", mOpacity); - config.setValue("showpickupchat", mPickupChatEnabled); - config.setValue("showpickupparticle", mPickupParticleEnabled); + config.showMonstersTakedDamage = mShowMonsterDamageEnabled; + config.visibleNames = mVisibleNamesEnabled; + config.speech = mSpeechMode; + config.showOwnName = mNameEnabled; + config.logNpcInGui = mNPCLogEnabled; + config.guiAlpha = mOpacity; + config.showPickupChat = mPickupChatEnabled; + config.showPickupParticle = mPickupParticleEnabled; } void Setup_Interface::action(const gcn::ActionEvent &event) @@ -220,38 +220,37 @@ void Setup_Interface::action(const gcn::ActionEvent &event) if (id == "guialpha") { - config.setValue("guialpha", mAlphaSlider->getValue()); + config.guiAlpha = mAlphaSlider->getValue(); } else if (id == "monsterdamage") { - config.setValue("showMonstersTakedDamage", mShowMonsterDamageCheckBox->isSelected()); + config.showMonstersTakedDamage = mShowMonsterDamageCheckBox->isSelected(); } else if (id == "visiblenames") { - config.setValue("visiblenames", mVisibleNamesCheckBox->isSelected()); + config.visibleNames = mVisibleNamesCheckBox->isSelected(); } else if (id == "pickupchat") { - config.setValue("showpickupchat", mPickupChatCheckBox->isSelected()); + config.showPickupChat = mPickupChatCheckBox->isSelected(); } else if (id == "pickupparticle") { - config.setValue("showpickupparticle", - mPickupParticleCheckBox->isSelected()); + config.showPickupParticle = mPickupParticleCheckBox->isSelected(); } else if (id == "speech") { auto val = (Being::Speech)mSpeechSlider->getValue(); mSpeechLabel->setCaption(speechModeToString(val)); mSpeechSlider->setValue(val); - config.setValue("speech", val); + config.speech = val; } else if (id == "showownname") { - config.setValue("showownname", mNameCheckBox->isSelected()); + config.showOwnName = mNameCheckBox->isSelected(); } else if (id == "lognpc") { - config.setValue("logNpcInGui", mNPCLogCheckBox->isSelected()); + config.logNpcInGui = mNPCLogCheckBox->isSelected(); } } diff --git a/src/gui/setup_joystick.cpp b/src/gui/setup_joystick.cpp index 1109f06e..17e86ea9 100644 --- a/src/gui/setup_joystick.cpp +++ b/src/gui/setup_joystick.cpp @@ -39,7 +39,7 @@ Setup_Joystick::Setup_Joystick(): { setName(_("Joystick")); - mJoystickEnabled = config.getBoolValue("joystickEnabled"); + mJoystickEnabled = config.joystickEnabled; mJoystickCheckBox->setSelected(mJoystickEnabled); mJoystickCheckBox->addActionListener(this); @@ -90,7 +90,5 @@ void Setup_Joystick::cancel() void Setup_Joystick::apply() { - config.setValue("joystickEnabled", - joystick ? joystick->isEnabled() : false); + config.joystickEnabled = joystick && joystick->isEnabled(); } - diff --git a/src/gui/setup_keyboard.h b/src/gui/setup_keyboard.h index 1ecb5ea3..1c9d1733 100644 --- a/src/gui/setup_keyboard.h +++ b/src/gui/setup_keyboard.h @@ -29,8 +29,6 @@ #include <guichan/actionlistener.hpp> -#include <string> - class Setup_Keyboard : public SetupTab, public gcn::ActionListener { public: diff --git a/src/gui/setup_players.cpp b/src/gui/setup_players.cpp index a771d7ae..501fc83a 100644 --- a/src/gui/setup_players.cpp +++ b/src/gui/setup_players.cpp @@ -201,9 +201,6 @@ public: #define ACTION_DELETE "delete" #define ACTION_TABLE "table" #define ACTION_STRATEGY "strategy" -#define ACTION_WHISPER_TAB "whisper tab" -#define ACTION_SHOW_GENDER "show gender" -#define ACTION_ENABLE_CHAT_LOG "enable log" Setup_Players::Setup_Players(): mPlayerTableTitleModel(new StaticTableModel(1, COLUMNS_NR)), @@ -216,12 +213,9 @@ Setup_Players::Setup_Players(): mDefaultWhisper(new CheckBox(_("Allow whispers"), player_relations.getDefault() & PlayerPermissions::WHISPER)), mDeleteButton(new Button(_("Delete"), ACTION_DELETE, this)), - mWhisperTab(config.getBoolValue("whispertab")), - mWhisperTabCheckBox(new CheckBox(_("Put all whispers in tabs"), mWhisperTab)), - mShowGender(config.getBoolValue("showgender")), - mShowGenderCheckBox(new CheckBox(_("Show gender"), mShowGender)), - mEnableChatLog(config.getBoolValue("enableChatLog")), - mEnableChatLogCheckBox(new CheckBox(_("Enable Chat log"), mEnableChatLog)) + mWhisperTabCheckBox(new CheckBox(_("Put all whispers in tabs"), config.whisperTab)), + mShowGenderCheckBox(new CheckBox(_("Show gender"), config.showGender)), + mEnableChatLogCheckBox(new CheckBox(_("Enable Chat log"), config.enableChatLog)) { setName(_("Players")); @@ -253,27 +247,18 @@ Setup_Players::Setup_Players(): mIgnoreActionChoicesBox->setActionEventId(ACTION_STRATEGY); mIgnoreActionChoicesBox->addActionListener(this); - int ignore_strategy_index = 0; // safe default + int ignoreStrategyIndex = 0; // safe default - if (player_relations.getPlayerIgnoreStrategy()) + if (auto ignoreStrategy = player_relations.getPlayerIgnoreStrategy()) { - ignore_strategy_index = player_relations.getPlayerIgnoreStrategyIndex( - player_relations.getPlayerIgnoreStrategy()->mShortName); - if (ignore_strategy_index < 0) - ignore_strategy_index = 0; + ignoreStrategyIndex = player_relations.getPlayerIgnoreStrategyIndex( + ignoreStrategy->mShortName); + if (ignoreStrategyIndex < 0) + ignoreStrategyIndex = 0; } - mIgnoreActionChoicesBox->setSelected(ignore_strategy_index); + mIgnoreActionChoicesBox->setSelected(ignoreStrategyIndex); mIgnoreActionChoicesBox->adjustHeight(); - mWhisperTabCheckBox->setActionEventId(ACTION_WHISPER_TAB); - mWhisperTabCheckBox->addActionListener(this); - - mShowGenderCheckBox->setActionEventId(ACTION_SHOW_GENDER); - mShowGenderCheckBox->addActionListener(this); - - mEnableChatLogCheckBox->setActionEventId(ACTION_ENABLE_CHAT_LOG); - mEnableChatLogCheckBox->addActionListener(this); - reset(); // Do the layout @@ -323,26 +308,22 @@ void Setup_Players::apply() PlayerPermissions::TRADE : 0) | (mDefaultWhisper->isSelected() ? PlayerPermissions::WHISPER : 0)); - config.setValue("whispertab", mWhisperTab); - bool showGender = config.getBoolValue("showgender"); + const bool showGenderChanged = config.showGender != mShowGenderCheckBox->isSelected(); - config.setValue("showgender", mShowGender); + config.whisperTab = mWhisperTabCheckBox->isSelected(); + config.showGender = mShowGenderCheckBox->isSelected(); + config.enableChatLog = mEnableChatLogCheckBox->isSelected(); - if (actorSpriteManager && mShowGender != showGender) + if (actorSpriteManager && showGenderChanged) actorSpriteManager->updatePlayerNames(); - - config.setValue("enableChatLog", mEnableChatLog); } void Setup_Players::cancel() { - mWhisperTab = config.getBoolValue("whispertab"); - mWhisperTabCheckBox->setSelected(mWhisperTab); - mShowGender = config.getBoolValue("showgender"); - mShowGenderCheckBox->setSelected(mShowGender); - mEnableChatLog = config.getBoolValue("enableChatLog"); - mEnableChatLogCheckBox->setSelected(mEnableChatLog); + mWhisperTabCheckBox->setSelected(config.whisperTab); + mShowGenderCheckBox->setSelected(config.showGender); + mEnableChatLogCheckBox->setSelected(config.enableChatLog); } void Setup_Players::action(const gcn::ActionEvent &event) @@ -380,18 +361,6 @@ void Setup_Players::action(const gcn::ActionEvent &event) player_relations.setPlayerIgnoreStrategy(s); } - else if (event.getId() == ACTION_WHISPER_TAB) - { - mWhisperTab = mWhisperTabCheckBox->isSelected(); - } - else if (event.getId() == ACTION_SHOW_GENDER) - { - mShowGender = mShowGenderCheckBox->isSelected(); - } - else if (event.getId() == ACTION_ENABLE_CHAT_LOG) - { - mEnableChatLog = mEnableChatLogCheckBox->isSelected(); - } } void Setup_Players::playerRelationsUpdated() diff --git a/src/gui/setup_players.h b/src/gui/setup_players.h index 758c646d..48a08e83 100644 --- a/src/gui/setup_players.h +++ b/src/gui/setup_players.h @@ -65,13 +65,8 @@ private: gcn::ListModel *mIgnoreActionChoicesModel; gcn::DropDown *mIgnoreActionChoicesBox; - bool mWhisperTab; gcn::CheckBox *mWhisperTabCheckBox; - - bool mShowGender; gcn::CheckBox *mShowGenderCheckBox; - - bool mEnableChatLog; gcn::CheckBox *mEnableChatLogCheckBox; }; diff --git a/src/gui/setup_video.cpp b/src/gui/setup_video.cpp index 5f7dc7b4..efa56cb8 100644 --- a/src/gui/setup_video.cpp +++ b/src/gui/setup_video.cpp @@ -186,7 +186,7 @@ private: static const char *overlayDetailToString(int detail) { if (detail == -1) - detail = config.getIntValue("OverlayDetail"); + detail = config.overlayDetail; switch (detail) { @@ -200,7 +200,7 @@ static const char *overlayDetailToString(int detail) static const char *particleDetailToString(int detail) { if (detail == -1) - detail = 3 - config.getIntValue("particleEmitterSkip"); + detail = 3 - config.particleEmitterSkip; switch (detail) { @@ -214,10 +214,10 @@ static const char *particleDetailToString(int detail) Setup_Video::Setup_Video(): mVideoSettings(Client::getVideo().settings()), - mCustomCursorEnabled(config.getBoolValue("customcursor")), - mParticleEffectsEnabled(config.getBoolValue("particleeffects")), - mFps(config.getIntValue("fpslimit")), - mSDLTransparencyDisabled(config.getBoolValue("disableTransparency")), + mCustomCursorEnabled(config.customCursor), + mParticleEffectsEnabled(config.particleEffects), + mFps(config.fpsLimit), + mSDLTransparencyDisabled(config.disableTransparency), mWindowModeListModel(new StringListModel({ _("Windowed"), _("Windowed Fullscreen"), _("Fullscreen") })), mResolutionListModel(new ResolutionListModel), mScaleListModel(new ScaleListModel(mVideoSettings)), @@ -231,10 +231,10 @@ Setup_Video::Setup_Video(): mFpsCheckBox(new CheckBox(_("FPS limit:"))), mFpsSlider(new Slider(10, 120)), mFpsLabel(new Label), - mOverlayDetail(config.getIntValue("OverlayDetail")), + mOverlayDetail(config.overlayDetail), mOverlayDetailSlider(new Slider(0, 2)), mOverlayDetailField(new Label), - mParticleDetail(3 - config.getIntValue("particleEmitterSkip")), + mParticleDetail(3 - config.particleEmitterSkip), mParticleDetailSlider(new Slider(0, 3)), mParticleDetailField(new Label), mDisableSDLTransparencyCheckBox( @@ -361,11 +361,11 @@ void Setup_Video::apply() if (video.apply(mVideoSettings)) { - config.setValue("windowmode", static_cast<int>(mVideoSettings.windowMode)); - config.setValue("scale", mVideoSettings.userScale); - config.setValue("vsync", mVideoSettings.vsync); - config.setValue("screenwidth", mVideoSettings.width); - config.setValue("screenheight", mVideoSettings.height); + config.windowMode = mVideoSettings.windowMode; + config.scale = mVideoSettings.userScale; + config.vsync = mVideoSettings.vsync; + config.screenWidth = mVideoSettings.width; + config.screenHeight = mVideoSettings.height; Client::instance()->checkGraphicsSize(); } @@ -377,7 +377,7 @@ void Setup_Video::apply() // OpenGL change if (mOpenGLCheckBox->isSelected() != mVideoSettings.openGL) { - config.setValue("opengl", mOpenGLCheckBox->isSelected()); + config.opengl = mOpenGLCheckBox->isSelected(); // OpenGL can currently only be changed by restarting, notify user. if (mOpenGLCheckBox->isSelected()) @@ -397,7 +397,7 @@ void Setup_Video::apply() // If LowCPU is enabled from a disabled state we warn the user else if (mDisableSDLTransparencyCheckBox->isSelected()) { - if (!config.getBoolValue("disableTransparency")) + if (!config.disableTransparency) { new OkDialog(_("Transparency disabled"), _("You must restart to apply changes.")); @@ -405,29 +405,28 @@ void Setup_Video::apply() } else { - if (config.getBoolValue("disableTransparency")) + if (config.disableTransparency) { new OkDialog(_("Transparency enabled"), _("You must restart to apply changes.")); } } - config.setValue("disableTransparency", - mDisableSDLTransparencyCheckBox->isSelected()); + config.disableTransparency = mDisableSDLTransparencyCheckBox->isSelected(); mFps = mFpsCheckBox->isSelected() ? (int) mFpsSlider->getValue() : 0; mFpsSlider->setEnabled(mFps > 0); // FPS change - config.setValue("fpslimit", mFps); + config.fpsLimit = mFps; // We sync old and new values at apply time - mVideoSettings.windowMode = static_cast<WindowMode>(config.getIntValue("windowmode")); - mVideoSettings.vsync = config.getBoolValue("vsync"); - mVideoSettings.openGL = config.getBoolValue("opengl"); - mCustomCursorEnabled = config.getBoolValue("customcursor"); - mParticleEffectsEnabled = config.getBoolValue("particleeffects"); - mOverlayDetail = config.getIntValue("OverlayDetail"); - mSDLTransparencyDisabled = config.getBoolValue("disableTransparency"); + mVideoSettings.windowMode = config.windowMode; + mVideoSettings.vsync = config.vsync; + mVideoSettings.openGL = config.opengl; + mCustomCursorEnabled = config.customCursor; + mParticleEffectsEnabled = config.particleEffects; + mOverlayDetail = config.overlayDetail; + mSDLTransparencyDisabled = config.disableTransparency; } void Setup_Video::cancel() @@ -452,12 +451,12 @@ void Setup_Video::cancel() mDisableSDLTransparencyCheckBox->setSelected(mSDLTransparencyDisabled); mDisableSDLTransparencyCheckBox->setEnabled(!mVideoSettings.openGL); - config.setValue("windowmode", static_cast<int>(mVideoSettings.windowMode)); + config.windowMode = mVideoSettings.windowMode; - config.setValue("customcursor", mCustomCursorEnabled); - config.setValue("particleeffects", mParticleEffectsEnabled); - config.setValue("opengl", mVideoSettings.openGL); - config.setValue("disableTransparency", mSDLTransparencyDisabled); + config.customCursor = mCustomCursorEnabled; + config.particleEffects = mParticleEffectsEnabled; + config.opengl = mVideoSettings.openGL; + config.disableTransparency = mSDLTransparencyDisabled; } void Setup_Video::action(const gcn::ActionEvent &event) @@ -490,12 +489,11 @@ void Setup_Video::action(const gcn::ActionEvent &event) } else if (id == "customcursor") { - config.setValue("customcursor", mCustomCursorCheckBox->isSelected()); + config.customCursor = mCustomCursorCheckBox->isSelected(); } else if (id == "particleeffects") { - config.setValue("particleeffects", - mParticleEffectsCheckBox->isSelected()); + config.particleEffects = mParticleEffectsCheckBox->isSelected(); Particle::enabled = mParticleEffectsCheckBox->isSelected(); if (Game::instance()) @@ -508,13 +506,13 @@ void Setup_Video::action(const gcn::ActionEvent &event) { int val = (int) mOverlayDetailSlider->getValue(); mOverlayDetailField->setCaption(overlayDetailToString(val)); - config.setValue("OverlayDetail", val); + config.overlayDetail = val; } else if (id == "particledetailslider") { int val = (int) mParticleDetailSlider->getValue(); mParticleDetailField->setCaption(particleDetailToString(val)); - config.setValue("particleEmitterSkip", 3 - val); + config.particleEmitterSkip = 3 - val; Particle::emitterSkip = 4 - val; } else if (id == "fpslimitcheckbox" || id == "fpslimitslider") diff --git a/src/gui/updaterwindow.cpp b/src/gui/updaterwindow.cpp index a92911b4..772df725 100644 --- a/src/gui/updaterwindow.cpp +++ b/src/gui/updaterwindow.cpp @@ -464,7 +464,7 @@ void UpdaterWindow::logic() const UpdateFile &thisFile = mUpdateFiles[mUpdateIndex]; if (!thisFile.required) { - if (!(thisFile.type == "music" && config.getBoolValue("download-music"))) + if (!(thisFile.type == "music" && config.downloadMusic)) { mUpdateIndex++; break; diff --git a/src/gui/viewport.cpp b/src/gui/viewport.cpp index 8fcca014..558ce0e6 100644 --- a/src/gui/viewport.cpp +++ b/src/gui/viewport.cpp @@ -49,11 +49,6 @@ Viewport::Viewport() setOpaque(false); addMouseListener(this); - mScrollLaziness = config.getIntValue("ScrollLaziness"); - mScrollRadius = config.getIntValue("ScrollRadius"); - mScrollCenterOffsetX = config.getIntValue("ScrollCenterOffsetX"); - mScrollCenterOffsetY = config.getIntValue("ScrollCenterOffsetY"); - mPopupMenu = new PopupMenu; mBeingPopup = new BeingPopup; @@ -95,8 +90,8 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) auto *graphics = static_cast<Graphics*>(gcnGraphics); // Calculate viewpoint - int midTileX = (graphics->getWidth() + mScrollCenterOffsetX) / 2; - int midTileY = (graphics->getHeight() + mScrollCenterOffsetX) / 2; + int midTileX = (graphics->getWidth() + config.scrollCenterOffsetX) / 2; + int midTileY = (graphics->getHeight() + config.scrollCenterOffsetY) / 2; const Vector &playerPos = local_player->getPosition(); const int player_x = (int) playerPos.x - midTileX; @@ -105,34 +100,34 @@ void Viewport::draw(gcn::Graphics *gcnGraphics) const float ticks = Time::deltaTimeMs() / static_cast<float>(MILLISECONDS_IN_A_TICK); float scrollFraction = 1.0f; - if (mScrollLaziness > 1) + if (config.scrollLaziness > 1) { - // mScrollLaziness defines the fraction of the desired camera movement + // settings.ScrollLaziness defines the fraction of the desired camera movement // that is applied every 10ms. To make this work independently of the // frame duration, we calculate the actual scroll fraction based on the // time delta. - scrollFraction = 1.0f - std::pow(1.0f - 1.0f / mScrollLaziness, ticks); + scrollFraction = 1.0f - std::pow(1.0f - 1.0f / config.scrollLaziness, ticks); } // Apply lazy scrolling - if (player_x > mPixelViewX + mScrollRadius) + if (player_x > mPixelViewX + config.scrollRadius) { - mPixelViewX += (player_x - mPixelViewX - mScrollRadius) * + mPixelViewX += (player_x - mPixelViewX - config.scrollRadius) * scrollFraction; } - if (player_x < mPixelViewX - mScrollRadius) + if (player_x < mPixelViewX - config.scrollRadius) { - mPixelViewX += (player_x - mPixelViewX + mScrollRadius) * + mPixelViewX += (player_x - mPixelViewX + config.scrollRadius) * scrollFraction; } - if (player_y > mPixelViewY + mScrollRadius) + if (player_y > mPixelViewY + config.scrollRadius) { - mPixelViewY += (player_y - mPixelViewY - mScrollRadius) * + mPixelViewY += (player_y - mPixelViewY - config.scrollRadius) * scrollFraction; } - if (player_y < mPixelViewY - mScrollRadius) + if (player_y < mPixelViewY - config.scrollRadius) { - mPixelViewY += (player_y - mPixelViewY + mScrollRadius) * + mPixelViewY += (player_y - mPixelViewY + config.scrollRadius) * scrollFraction; } @@ -624,14 +619,4 @@ void Viewport::event(Event::Channel channel, const Event &event) if (mHoverItem == actor) mHoverItem = nullptr; } - else if (channel == Event::ConfigChannel && - event.getType() == Event::ConfigOptionChanged) - { - const std::string &option = event.getString("option"); - if (option == "ScrollLaziness" || option == "ScrollRadius") - { - mScrollLaziness = config.getIntValue("ScrollLaziness"); - mScrollRadius = config.getIntValue("ScrollRadius"); - } - } } diff --git a/src/gui/viewport.h b/src/gui/viewport.h index ee7eb96f..b69a73b6 100644 --- a/src/gui/viewport.h +++ b/src/gui/viewport.h @@ -194,10 +194,6 @@ class Viewport : public WindowContainer, public gcn::MouseListener, Map *mMap = nullptr; /**< The current map. */ - int mScrollRadius; - int mScrollLaziness; - int mScrollCenterOffsetX; - int mScrollCenterOffsetY; int mMouseX = 0; /**< Current mouse position in pixels. */ int mMouseY = 0; /**< Current mouse position in pixels. */ float mPixelViewX = 0.0f; /**< Current viewpoint in pixels. */ diff --git a/src/gui/widgets/button.cpp b/src/gui/widgets/button.cpp index 5c691705..274f329b 100644 --- a/src/gui/widgets/button.cpp +++ b/src/gui/widgets/button.cpp @@ -191,7 +191,7 @@ Button::~Button() void Button::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (mAlpha != alpha) diff --git a/src/gui/widgets/chattab.cpp b/src/gui/widgets/chattab.cpp index 7a840cc6..1584eb0a 100644 --- a/src/gui/widgets/chattab.cpp +++ b/src/gui/widgets/chattab.cpp @@ -52,7 +52,7 @@ ChatTab::ChatTab(const std::string &name) mTextOutput = new BrowserBox(BrowserBox::AUTO_WRAP); mTextOutput->setWrapIndent(15); - mTextOutput->setMaxRows(config.getIntValue("ChatLogLength")); + mTextOutput->setMaxRows(config.chatLogLength); mTextOutput->setLinkHandler(chatWindow->mItemLinkHandler); mScrollArea = new ScrollArea(mTextOutput); @@ -216,7 +216,7 @@ void ChatTab::chatLog(std::string line, Own own, bool ignoreRecord) line = lineColor + timeStr.str() + tmp.nick + tmp.text; - if (config.getBoolValue("enableChatLog") && !ignoreRecord) + if (config.enableChatLog && !ignoreRecord) saveToLogFile(line); // We look if the Vertical Scroll Bar is set at the max before diff --git a/src/gui/widgets/checkbox.cpp b/src/gui/widgets/checkbox.cpp index 0554bad6..274855fd 100644 --- a/src/gui/widgets/checkbox.cpp +++ b/src/gui/widgets/checkbox.cpp @@ -89,7 +89,7 @@ void CheckBox::draw(gcn::Graphics* graphics) void CheckBox::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (mAlpha != alpha) diff --git a/src/gui/widgets/dropdown.cpp b/src/gui/widgets/dropdown.cpp index c548570d..8811eb8d 100644 --- a/src/gui/widgets/dropdown.cpp +++ b/src/gui/widgets/dropdown.cpp @@ -110,7 +110,7 @@ DropDown::~DropDown() void DropDown::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (mAlpha != alpha) diff --git a/src/gui/widgets/emoteshortcutcontainer.cpp b/src/gui/widgets/emoteshortcutcontainer.cpp index c72d166f..8ecbc9bf 100644 --- a/src/gui/widgets/emoteshortcutcontainer.cpp +++ b/src/gui/widgets/emoteshortcutcontainer.cpp @@ -41,7 +41,7 @@ EmoteShortcutContainer::EmoteShortcutContainer() mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png"); - mBackgroundImg->setAlpha(config.getFloatValue("guialpha")); + mBackgroundImg->setAlpha(config.guiAlpha); mMaxItems = std::min(EmoteDB::getEmoteCount(), MAX_ITEMS); @@ -56,9 +56,9 @@ EmoteShortcutContainer::~EmoteShortcutContainer() void EmoteShortcutContainer::draw(gcn::Graphics *graphics) { - if (config.getFloatValue("guialpha") != mAlpha) + if (config.guiAlpha != mAlpha) { - mAlpha = config.getFloatValue("guialpha"); + mAlpha = config.guiAlpha; mBackgroundImg->setAlpha(mAlpha); } diff --git a/src/gui/widgets/itemshortcutcontainer.cpp b/src/gui/widgets/itemshortcutcontainer.cpp index e6db7a0b..0b8f0c8c 100644 --- a/src/gui/widgets/itemshortcutcontainer.cpp +++ b/src/gui/widgets/itemshortcutcontainer.cpp @@ -48,7 +48,7 @@ ItemShortcutContainer::ItemShortcutContainer() mBackgroundImg = Theme::getImageFromTheme("item_shortcut_bgr.png"); mMaxItems = itemShortcut->getItemCount(); - mBackgroundImg->setAlpha(config.getFloatValue("guialpha")); + mBackgroundImg->setAlpha(config.guiAlpha); mBoxHeight = mBackgroundImg->getHeight(); mBoxWidth = mBackgroundImg->getWidth(); @@ -62,9 +62,9 @@ ItemShortcutContainer::~ItemShortcutContainer() void ItemShortcutContainer::draw(gcn::Graphics *graphics) { - if (config.getFloatValue("guialpha") != mAlpha) + if (config.guiAlpha != mAlpha) { - mAlpha = config.getFloatValue("guialpha"); + mAlpha = config.guiAlpha; mBackgroundImg->setAlpha(mAlpha); } diff --git a/src/gui/widgets/listbox.cpp b/src/gui/widgets/listbox.cpp index fc4d8a8e..55f0f422 100644 --- a/src/gui/widgets/listbox.cpp +++ b/src/gui/widgets/listbox.cpp @@ -41,7 +41,7 @@ ListBox::ListBox(gcn::ListModel *listModel): void ListBox::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (mAlpha != alpha) diff --git a/src/gui/widgets/playerbox.cpp b/src/gui/widgets/playerbox.cpp index 671fad36..3bdd6bd1 100644 --- a/src/gui/widgets/playerbox.cpp +++ b/src/gui/widgets/playerbox.cpp @@ -59,7 +59,7 @@ PlayerBox::PlayerBox(const Being *being): } } - background.setAlpha(config.getFloatValue("guialpha")); + background.setAlpha(config.guiAlpha); textbox->decRef(); } @@ -90,9 +90,10 @@ void PlayerBox::draw(gcn::Graphics *graphics) mBeing->drawSpriteAt(static_cast<Graphics*>(graphics), x, y); } - if (config.getFloatValue("guialpha") != mAlpha) + if (config.guiAlpha != mAlpha) { - background.setAlpha(config.getFloatValue("guialpha")); + mAlpha = config.guiAlpha; + background.setAlpha(config.guiAlpha); } } diff --git a/src/gui/widgets/progressbar.cpp b/src/gui/widgets/progressbar.cpp index 523dde1c..9d41d1af 100644 --- a/src/gui/widgets/progressbar.cpp +++ b/src/gui/widgets/progressbar.cpp @@ -116,7 +116,7 @@ void ProgressBar::logic() void ProgressBar::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (mAlpha != alpha) diff --git a/src/gui/widgets/radiobutton.cpp b/src/gui/widgets/radiobutton.cpp index bb96d77c..92cdacd1 100644 --- a/src/gui/widgets/radiobutton.cpp +++ b/src/gui/widgets/radiobutton.cpp @@ -76,9 +76,9 @@ RadioButton::~RadioButton() void RadioButton::drawBox(gcn::Graphics* graphics) { - if (config.getFloatValue("guialpha") != mAlpha) + if (config.guiAlpha != mAlpha) { - mAlpha = config.getFloatValue("guialpha"); + mAlpha = config.guiAlpha; radioNormal->setAlpha(mAlpha); radioChecked->setAlpha(mAlpha); radioDisabled->setAlpha(mAlpha); diff --git a/src/gui/widgets/resizegrip.cpp b/src/gui/widgets/resizegrip.cpp index 1770fcb1..dd29a977 100644 --- a/src/gui/widgets/resizegrip.cpp +++ b/src/gui/widgets/resizegrip.cpp @@ -58,9 +58,9 @@ ResizeGrip::~ResizeGrip() void ResizeGrip::draw(gcn::Graphics *graphics) { - if (config.getFloatValue("guialpha") != mAlpha) + if (config.guiAlpha != mAlpha) { - mAlpha = config.getFloatValue("guialpha"); + mAlpha = config.guiAlpha; gripImage->setAlpha(mAlpha); } diff --git a/src/gui/widgets/scrollarea.cpp b/src/gui/widgets/scrollarea.cpp index 8e16b5b3..225a231d 100644 --- a/src/gui/widgets/scrollarea.cpp +++ b/src/gui/widgets/scrollarea.cpp @@ -100,7 +100,7 @@ void ScrollArea::init() a++; } } - background.setAlpha(config.getFloatValue("guialpha")); + background.setAlpha(config.guiAlpha); textbox->decRef(); @@ -128,8 +128,8 @@ void ScrollArea::init() } } - vMarker.setAlpha(config.getFloatValue("guialpha")); - vMarkerHi.setAlpha(config.getFloatValue("guialpha")); + vMarker.setAlpha(config.guiAlpha); + vMarkerHi.setAlpha(config.guiAlpha); vscroll->decRef(); vscrollHi->decRef(); @@ -203,8 +203,8 @@ void ScrollArea::logic() void ScrollArea::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), - Theme::instance()->getMinimumOpacity()); + float alpha = std::max(config.guiAlpha, + Theme::instance()->getMinimumOpacity()); if (alpha != mAlpha) { diff --git a/src/gui/widgets/shoplistbox.cpp b/src/gui/widgets/shoplistbox.cpp index d0c79af2..31c733a6 100644 --- a/src/gui/widgets/shoplistbox.cpp +++ b/src/gui/widgets/shoplistbox.cpp @@ -36,8 +36,6 @@ #include <guichan/font.hpp> #include <guichan/listmodel.hpp> -float ShopListBox::mAlpha = 1.0; - ShopListBox::ShopListBox(gcn::ListModel *listModel): ListBox(listModel) { @@ -72,10 +70,7 @@ void ShopListBox::draw(gcn::Graphics *gcnGraphics) if (!mListModel) return; - if (config.getFloatValue("guialpha") != mAlpha) - mAlpha = config.getFloatValue("guialpha"); - - const int alpha = (int)(mAlpha * 255.0f); + const int alpha = (int)(config.guiAlpha * 255.0f); const gcn::Color &highlightColor = Theme::getThemeColor(Theme::HIGHLIGHT, alpha); const gcn::Color &backgroundColor = diff --git a/src/gui/widgets/shoplistbox.h b/src/gui/widgets/shoplistbox.h index b5718ed3..4dbd756b 100644 --- a/src/gui/widgets/shoplistbox.h +++ b/src/gui/widgets/shoplistbox.h @@ -95,8 +95,6 @@ class ShopListBox : public ListBox unsigned int mRowHeight; /**< Row Height */ - static float mAlpha; - bool mPriceCheck; }; diff --git a/src/gui/widgets/slider.cpp b/src/gui/widgets/slider.cpp index fd21becf..a7ba37e8 100644 --- a/src/gui/widgets/slider.cpp +++ b/src/gui/widgets/slider.cpp @@ -123,7 +123,7 @@ void Slider::init() void Slider::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (alpha != mAlpha) diff --git a/src/gui/widgets/tab.cpp b/src/gui/widgets/tab.cpp index 08acd245..64f49eac 100644 --- a/src/gui/widgets/tab.cpp +++ b/src/gui/widgets/tab.cpp @@ -114,7 +114,7 @@ void Tab::init() void Tab::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); // TODO We don't need to do this for every tab on every draw diff --git a/src/gui/widgets/table.cpp b/src/gui/widgets/table.cpp index a74fc09e..905bb166 100644 --- a/src/gui/widgets/table.cpp +++ b/src/gui/widgets/table.cpp @@ -269,8 +269,8 @@ void GuiTable::draw(gcn::Graphics* graphics) if (!mModel) return; - if (config.getFloatValue("guialpha") != mAlpha) - mAlpha = config.getFloatValue("guialpha"); + if (config.guiAlpha != mAlpha) + mAlpha = config.guiAlpha; if (mOpaque) { diff --git a/src/gui/widgets/textfield.cpp b/src/gui/widgets/textfield.cpp index 3e1665d3..dd0adecd 100644 --- a/src/gui/widgets/textfield.cpp +++ b/src/gui/widgets/textfield.cpp @@ -69,7 +69,7 @@ TextField::TextField(const std::string &text, bool loseFocusOnTab): a++; } } - skin.setAlpha(config.getFloatValue("guialpha")); + skin.setAlpha(config.guiAlpha); textbox->decRef(); } @@ -87,7 +87,7 @@ TextField::~TextField() void TextField::updateAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); if (alpha != mAlpha) diff --git a/src/gui/widgets/textpreview.cpp b/src/gui/widgets/textpreview.cpp index 8b2c3a75..f9e85052 100644 --- a/src/gui/widgets/textpreview.cpp +++ b/src/gui/widgets/textpreview.cpp @@ -41,8 +41,8 @@ TextPreview::TextPreview(const std::string &text): void TextPreview::draw(gcn::Graphics* graphics) { - if (config.getFloatValue("guialpha") != mAlpha) - mAlpha = config.getFloatValue("guialpha"); + if (config.guiAlpha != mAlpha) + mAlpha = config.guiAlpha; int alpha = (int) (mAlpha * 255.0f); diff --git a/src/gui/widgets/window.cpp b/src/gui/widgets/window.cpp index 050e31da..8bf9d081 100644 --- a/src/gui/widgets/window.cpp +++ b/src/gui/widgets/window.cpp @@ -37,6 +37,9 @@ #include <guichan/exception.hpp> #include <guichan/focushandler.hpp> +#include <algorithm> +#include <cassert> + int Window::instances = 0; int Window::mouseResize = 0; @@ -503,33 +506,29 @@ void Window::mouseDragged(gcn::MouseEvent &event) void Window::loadWindowState() { - const std::string &name = mWindowName; - assert(!name.empty()); + assert(!mWindowName.empty()); + + constexpr WindowState defaultState; + auto s = config.windows.find(mWindowName); + const WindowState state = s == config.windows.end() ? defaultState + : s->second; - setPosition((int) config.getValue(name + "WinX", mDefaultX), - (int) config.getValue(name + "WinY", mDefaultY)); + setPosition(state.x.value_or(mDefaultX), + state.y.value_or(mDefaultY)); if (mSaveVisible) - setVisible((bool) config.getValue(name + "Visible", mDefaultVisible)); + setVisible(state.visible.value_or(mDefaultVisible)); if (mStickyButton) - setSticky((bool) config.getValue(name + "Sticky", isSticky())); + setSticky(state.sticky.value_or(isSticky())); if (mGrip) { - int width = (int) config.getValue(name + "WinWidth", mDefaultWidth); - int height = (int) config.getValue(name + "WinHeight", mDefaultHeight); - - if (getMinWidth() > width) - width = getMinWidth(); - else if (getMaxWidth() < width) - width = getMaxWidth(); - if (getMinHeight() > height) - height = getMinHeight(); - else if (getMaxHeight() < height) - height = getMaxHeight(); - - setSize(width, height); + const int width = state.width.value_or(mDefaultWidth); + const int height = state.height.value_or(mDefaultHeight); + + setSize(std::clamp(width, getMinWidth(), getMaxWidth()), + std::clamp(height, getMinHeight(), getMaxHeight())); } else { @@ -540,35 +539,29 @@ void Window::loadWindowState() ensureOnScreen(); } -void Window::saveWindowState() +void Window::saveWindowState() const { // Saving X, Y and Width and Height for resizables in the config - if (!mWindowName.empty() && mWindowName != "window") - { - config.setValue(mWindowName + "WinX", getX()); - config.setValue(mWindowName + "WinY", getY()); + if (mWindowName.empty()) + return; - if (mSaveVisible) - config.setValue(mWindowName + "Visible", isVisible()); + WindowState state; + state.x = getX(); + state.y = getY(); - if (mStickyButton) - config.setValue(mWindowName + "Sticky", isSticky()); + if (mSaveVisible) + state.visible = isVisible(); - if (mGrip) - { - if (getMinWidth() > getWidth()) - setWidth(getMinWidth()); - else if (getMaxWidth() < getWidth()) - setWidth(getMaxWidth()); - if (getMinHeight() > getHeight()) - setHeight(getMinHeight()); - else if (getMaxHeight() < getHeight()) - setHeight(getMaxHeight()); - - config.setValue(mWindowName + "WinWidth", getWidth()); - config.setValue(mWindowName + "WinHeight", getHeight()); - } + if (mStickyButton) + state.sticky = isSticky(); + + if (mGrip) + { + state.width = getWidth(); + state.height = getHeight(); } + + config.windows[mWindowName] = state; } void Window::setDefaultSize(int defaultX, int defaultY, @@ -701,7 +694,7 @@ int Window::getResizeHandles(gcn::MouseEvent &event) int Window::getGuiAlpha() { - float alpha = std::max(config.getFloatValue("guialpha"), + float alpha = std::max(config.guiAlpha, Theme::instance()->getMinimumOpacity()); return (int) (alpha * 255.0f); } diff --git a/src/gui/widgets/window.h b/src/gui/widgets/window.h index 975de335..bf6f363c 100644 --- a/src/gui/widgets/window.h +++ b/src/gui/widgets/window.h @@ -264,7 +264,7 @@ class Window : public gcn::Window, gcn::WidgetListener * Saves the window state so that when the window is reloaded, it'll * maintain its previous state and location. */ - void saveWindowState(); + void saveWindowState() const; /** * Set the default win pos and size. @@ -380,7 +380,7 @@ class Window : public gcn::Window, gcn::WidgetListener ResizeGrip *mGrip = nullptr; /**< Resize grip */ Window *mParent; /**< The parent window */ Layout *mLayout = nullptr; /**< Layout handler */ - std::string mWindowName = "window"; /**< Name of the window */ + std::string mWindowName; /**< Name of the window */ bool mShowTitle = true; /**< Window has a title bar */ bool mModal; /**< Window is modal */ bool mCloseButton = false; /**< Window has a close button */ diff --git a/src/itemshortcut.cpp b/src/itemshortcut.cpp index 577f76ae..643a594f 100644 --- a/src/itemshortcut.cpp +++ b/src/itemshortcut.cpp @@ -19,15 +19,14 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#include "itemshortcut.h" + #include "configuration.h" #include "event.h" #include "inventory.h" #include "item.h" -#include "itemshortcut.h" #include "playerinfo.h" -#include "utils/stringutils.h" - ItemShortcut *itemShortcut; ItemShortcut::ItemShortcut(): @@ -44,40 +43,44 @@ ItemShortcut::~ItemShortcut() void ItemShortcut::load() { for (int i = 0; i < SHORTCUT_ITEMS; i++) - { - int itemId = (int) config.getValue("shortcut" + toString(i), -1); + mItems[i] = -1; - mItems[i] = itemId; + for (auto &shortcut : config.itemShortcuts) + { + if (shortcut.index >= 0 && shortcut.index < SHORTCUT_ITEMS) + mItems[shortcut.index] = shortcut.itemId; } } void ItemShortcut::save() { + config.itemShortcuts.clear(); + for (int i = 0; i < SHORTCUT_ITEMS; i++) { - const int itemId = mItems[i] ? mItems[i] : -1; - config.setValue("shortcut" + toString(i), itemId); + if (mItems[i] >= 0) + config.itemShortcuts.push_back({ i, mItems[i] }); } } void ItemShortcut::useItem(int index) { - if (mItems[index]) + if (!mItems[index]) + return; + + Item *item = PlayerInfo::getInventory()->findItem(mItems[index]); + if (item && item->getQuantity()) { - Item *item = PlayerInfo::getInventory()->findItem(mItems[index]); - if (item && item->getQuantity()) + if (item->isEquippable()) { - if (item->isEquippable()) - { - if (item->isEquipped()) - item->doEvent(Event::DoUnequip); - else - item->doEvent(Event::DoEquip); - } + if (item->isEquipped()) + item->doEvent(Event::DoUnequip); else - { - item->doEvent(Event::DoUse); - } + item->doEvent(Event::DoEquip); + } + else + { + item->doEvent(Event::DoUse); } } } diff --git a/src/joystick.cpp b/src/joystick.cpp index a1da181c..c6e106bf 100644 --- a/src/joystick.cpp +++ b/src/joystick.cpp @@ -19,8 +19,9 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "configuration.h" #include "joystick.h" + +#include "configuration.h" #include "log.h" #include <cassert> @@ -40,10 +41,14 @@ void Joystick::init() logger->log("- %s", SDL_JoystickNameForIndex(i)); } -Joystick::Joystick(int no): - mDirection(0), - mCalibrating(false), - mEnabled(false) +Joystick::Joystick(int no) + : mDirection(0) + , mUpTolerance(config.upTolerance) + , mDownTolerance(config.downTolerance) + , mLeftTolerance(config.leftTolerance) + , mRightTolerance(config.rightTolerance) + , mCalibrating(false) + , mEnabled(config.joystickEnabled) { assert(no < joystickCount); @@ -60,12 +65,6 @@ Joystick::Joystick(int no): logger->log("Balls: %i", SDL_JoystickNumBalls(mJoystick)); logger->log("Hats: %i", SDL_JoystickNumHats(mJoystick)); logger->log("Buttons: %i", SDL_JoystickNumButtons(mJoystick)); - - mEnabled = config.getBoolValue("joystickEnabled"); - mUpTolerance = config.getIntValue("upTolerance"); - mDownTolerance = config.getIntValue("downTolerance"); - mLeftTolerance = config.getIntValue("leftTolerance"); - mRightTolerance = config.getIntValue("rightTolerance"); } Joystick::~Joystick() @@ -134,10 +133,10 @@ void Joystick::doCalibration() void Joystick::finishCalibration() { - config.setValue("leftTolerance", mLeftTolerance); - config.setValue("rightTolerance", mRightTolerance); - config.setValue("upTolerance", mUpTolerance); - config.setValue("downTolerance", mDownTolerance); + config.leftTolerance = mLeftTolerance; + config.rightTolerance = mRightTolerance; + config.upTolerance = mUpTolerance; + config.downTolerance = mDownTolerance; mCalibrating = false; } diff --git a/src/keyboardconfig.cpp b/src/keyboardconfig.cpp index a705197a..c4d7a26d 100644 --- a/src/keyboardconfig.cpp +++ b/src/keyboardconfig.cpp @@ -28,82 +28,80 @@ #include "utils/gettext.h" #include "utils/stringutils.h" -#include <SDL.h> - struct KeyData { const char *configField; - int defaultValue; + SDL_Keycode defaultValue; std::string caption; }; // keyData must be in same order as enum keyAction. static KeyData const keyData[KeyboardConfig::KEY_TOTAL] = { - {"keyMoveUp", SDLK_UP, _("Move Up")}, - {"keyMoveDown", SDLK_DOWN, _("Move Down")}, - {"keyMoveLeft", SDLK_LEFT, _("Move Left")}, - {"keyMoveRight", SDLK_RIGHT, _("Move Right")}, - {"keyAttack", SDLK_LCTRL, _("Attack")}, - {"keyTargetAttack", SDLK_x, _("Target & Attack")}, - {"keySmilie", SDLK_LALT, _("Smilie")}, - {"keyTalk", SDLK_t, _("Talk")}, - {"keyTarget", SDLK_LSHIFT, _("Stop Attack")}, - {"keyTargetClosest", SDLK_a, _("Target Monster")}, - {"keyTargetNPC", SDLK_n, _("Target NPC")}, - {"keyTargetPlayer", SDLK_q, _("Target Player")}, - {"keyPickup", SDLK_z, _("Pickup")}, - {"keyHideWindows", SDLK_h, _("Hide Windows")}, - {"keyBeingSit", SDLK_s, _("Sit")}, - {"keyScreenshot", SDLK_p, _("Screenshot")}, - {"keyTrade", SDLK_r, _("Enable/Disable Trading")}, - {"keyShortcut1", SDLK_1, strprintf(_("Item Shortcut %d"), 1)}, - {"keyShortcut2", SDLK_2, strprintf(_("Item Shortcut %d"), 2)}, - {"keyShortcut3", SDLK_3, strprintf(_("Item Shortcut %d"), 3)}, - {"keyShortcut4", SDLK_4, strprintf(_("Item Shortcut %d"), 4)}, - {"keyShortcut5", SDLK_5, strprintf(_("Item Shortcut %d"), 5)}, - {"keyShortcut6", SDLK_6, strprintf(_("Item Shortcut %d"), 6)}, - {"keyShortcut7", SDLK_7, strprintf(_("Item Shortcut %d"), 7)}, - {"keyShortcut8", SDLK_8, strprintf(_("Item Shortcut %d"), 8)}, - {"keyShortcut9", SDLK_9, strprintf(_("Item Shortcut %d"), 9)}, - {"keyShortcut10", SDLK_0, strprintf(_("Item Shortcut %d"), 10)}, - {"keyShortcut11", SDLK_MINUS, strprintf(_("Item Shortcut %d"), 11)}, - {"keyShortcut12", SDLK_EQUALS, strprintf(_("Item Shortcut %d"), 12)}, - {"keyWindowHelp", SDLK_F1, _("Help Window")}, - {"keyWindowStatus", SDLK_F2, _("Status Window")}, - {"keyWindowInventory", SDLK_F3, _("Inventory Window")}, - {"keyWindowEquipment", SDLK_F4, _("Equipment Window")}, - {"keyWindowSkill", SDLK_F5, _("Skill Window")}, - {"keyWindowMinimap", SDLK_F6, _("Minimap Window")}, - {"keyWindowChat", SDLK_F7, _("Chat Window")}, - {"keyWindowShortcut", SDLK_F8, _("Item Shortcut Window")}, - {"keyWindowSetup", SDLK_F9, _("Setup Window")}, - {"keyWindowDebug", SDLK_F10, _("Debug Window")}, - {"keyWindowSocial", SDLK_F11, _("Social Window")}, - {"keyWindowEmoteBar", SDLK_F12, _("Emote Shortcut Window")}, - {"keyWindowOutfit", SDLK_o, _("Outfits Window")}, - {"keyWearOutfit", SDLK_RCTRL, _("Wear Outfit")}, - {"keyCopyOutfit", SDLK_RALT, _("Copy Outfit")}, - {"keyEmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1)}, - {"keyEmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2)}, - {"keyEmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3)}, - {"keyEmoteShortcut4", SDLK_4, strprintf(_("Emote Shortcut %d"), 4)}, - {"keyEmoteShortcut5", SDLK_5, strprintf(_("Emote Shortcut %d"), 5)}, - {"keyEmoteShortcut6", SDLK_6, strprintf(_("Emote Shortcut %d"), 6)}, - {"keyEmoteShortcut7", SDLK_7, strprintf(_("Emote Shortcut %d"), 7)}, - {"keyEmoteShortcut8", SDLK_8, strprintf(_("Emote Shortcut %d"), 8)}, - {"keyEmoteShortcut9", SDLK_9, strprintf(_("Emote Shortcut %d"), 9)}, - {"keyEmoteShortcut10", SDLK_0, strprintf(_("Emote Shortcut %d"), 10)}, - {"keyEmoteShortcut11", SDLK_MINUS, strprintf(_("Emote Shortcut %d"), 11)}, - {"keyEmoteShortcut12", SDLK_EQUALS, strprintf(_("Emote Shortcut %d"), 12)}, - {"keyChat", SDLK_RETURN, _("Toggle Chat")}, - {"keyChatScrollUp", SDLK_PAGEUP, _("Scroll Chat Up")}, - {"keyChatScrollDown", SDLK_PAGEDOWN, _("Scroll Chat Down")}, - {"keyChatPrevTab", SDLK_LEFTBRACKET, _("Previous Chat Tab")}, - {"keyChatNextTab", SDLK_RIGHTBRACKET, _("Next Chat Tab")}, - {"keyOK", SDLK_SPACE, _("Select OK")}, - {"keyQuit", SDLK_ESCAPE, _("Quit")}, - {"keyIgnoreInput1", SDLK_LGUI, _("Ignore input 1")}, - {"keyIgnoreInput2", SDLK_RGUI, _("Ignore input 2")} + { "MoveUp", SDLK_UP, _("Move Up") }, + { "MoveDown", SDLK_DOWN, _("Move Down") }, + { "MoveLeft", SDLK_LEFT, _("Move Left") }, + { "MoveRight", SDLK_RIGHT, _("Move Right") }, + { "Attack", SDLK_LCTRL, _("Attack") }, + { "TargetAttack", SDLK_x, _("Target & Attack") }, + { "Smilie", SDLK_LALT, _("Smilie") }, + { "Talk", SDLK_t, _("Talk") }, + { "Target", SDLK_LSHIFT, _("Stop Attack") }, + { "TargetClosest", SDLK_a, _("Target Monster") }, + { "TargetNPC", SDLK_n, _("Target NPC") }, + { "TargetPlayer", SDLK_q, _("Target Player") }, + { "Pickup", SDLK_z, _("Pickup") }, + { "HideWindows", SDLK_h, _("Hide Windows") }, + { "BeingSit", SDLK_s, _("Sit") }, + { "Screenshot", SDLK_p, _("Screenshot") }, + { "Trade", SDLK_r, _("Enable/Disable Trading") }, + { "Shortcut1", SDLK_1, strprintf(_("Item Shortcut %d"), 1) }, + { "Shortcut2", SDLK_2, strprintf(_("Item Shortcut %d"), 2) }, + { "Shortcut3", SDLK_3, strprintf(_("Item Shortcut %d"), 3) }, + { "Shortcut4", SDLK_4, strprintf(_("Item Shortcut %d"), 4) }, + { "Shortcut5", SDLK_5, strprintf(_("Item Shortcut %d"), 5) }, + { "Shortcut6", SDLK_6, strprintf(_("Item Shortcut %d"), 6) }, + { "Shortcut7", SDLK_7, strprintf(_("Item Shortcut %d"), 7) }, + { "Shortcut8", SDLK_8, strprintf(_("Item Shortcut %d"), 8) }, + { "Shortcut9", SDLK_9, strprintf(_("Item Shortcut %d"), 9) }, + { "Shortcut10", SDLK_0, strprintf(_("Item Shortcut %d"), 10) }, + { "Shortcut11", SDLK_MINUS, strprintf(_("Item Shortcut %d"), 11) }, + { "Shortcut12", SDLK_EQUALS, strprintf(_("Item Shortcut %d"), 12) }, + { "WindowHelp", SDLK_F1, _("Help Window") }, + { "WindowStatus", SDLK_F2, _("Status Window") }, + { "WindowInventory", SDLK_F3, _("Inventory Window") }, + { "WindowEquipment", SDLK_F4, _("Equipment Window") }, + { "WindowSkill", SDLK_F5, _("Skill Window") }, + { "WindowMinimap", SDLK_F6, _("Minimap Window") }, + { "WindowChat", SDLK_F7, _("Chat Window") }, + { "WindowShortcut", SDLK_F8, _("Item Shortcut Window") }, + { "WindowSetup", SDLK_F9, _("Setup Window") }, + { "WindowDebug", SDLK_F10, _("Debug Window") }, + { "WindowSocial", SDLK_F11, _("Social Window") }, + { "WindowEmoteBar", SDLK_F12, _("Emote Shortcut Window") }, + { "WindowOutfit", SDLK_o, _("Outfits Window") }, + { "WearOutfit", SDLK_RCTRL, _("Wear Outfit") }, + { "CopyOutfit", SDLK_RALT, _("Copy Outfit") }, + { "EmoteShortcut1", SDLK_1, strprintf(_("Emote Shortcut %d"), 1) }, + { "EmoteShortcut2", SDLK_2, strprintf(_("Emote Shortcut %d"), 2) }, + { "EmoteShortcut3", SDLK_3, strprintf(_("Emote Shortcut %d"), 3) }, + { "EmoteShortcut4", SDLK_4, strprintf(_("Emote Shortcut %d"), 4) }, + { "EmoteShortcut5", SDLK_5, strprintf(_("Emote Shortcut %d"), 5) }, + { "EmoteShortcut6", SDLK_6, strprintf(_("Emote Shortcut %d"), 6) }, + { "EmoteShortcut7", SDLK_7, strprintf(_("Emote Shortcut %d"), 7) }, + { "EmoteShortcut8", SDLK_8, strprintf(_("Emote Shortcut %d"), 8) }, + { "EmoteShortcut9", SDLK_9, strprintf(_("Emote Shortcut %d"), 9) }, + { "EmoteShortcut10", SDLK_0, strprintf(_("Emote Shortcut %d"), 10) }, + { "EmoteShortcut11", SDLK_MINUS, strprintf(_("Emote Shortcut %d"), 11) }, + { "EmoteShortcut12", SDLK_EQUALS, strprintf(_("Emote Shortcut %d"), 12) }, + { "Chat", SDLK_RETURN, _("Toggle Chat") }, + { "ChatScrollUp", SDLK_PAGEUP, _("Scroll Chat Up") }, + { "ChatScrollDown", SDLK_PAGEDOWN, _("Scroll Chat Down") }, + { "ChatPrevTab", SDLK_LEFTBRACKET, _("Previous Chat Tab") }, + { "ChatNextTab", SDLK_RIGHTBRACKET, _("Next Chat Tab") }, + { "OK", SDLK_SPACE, _("Select OK") }, + { "Quit", SDLK_ESCAPE, _("Quit") }, + { "IgnoreInput1", SDLK_LGUI, _("Ignore input 1") }, + { "IgnoreInput2", SDLK_RGUI, _("Ignore input 2") } }; void KeyboardConfig::init() @@ -112,7 +110,6 @@ void KeyboardConfig::init() { mKey[i].configField = keyData[i].configField; mKey[i].defaultValue = keyData[i].defaultValue; - mKey[i].caption = keyData[i].caption; mKey[i].value = KEY_NO_VALUE; } mNewKeyIndex = KEY_NO_VALUE; @@ -125,15 +122,31 @@ void KeyboardConfig::retrieve() { for (auto &key : mKey) { - key.value = (int) config.getValue(key.configField, key.defaultValue); + const auto keyIt = config.keys.find(key.configField); + if (keyIt != config.keys.end()) + { + key.value = SDL_GetKeyFromName(keyIt->second.c_str()); + + if (key.value == SDLK_UNKNOWN) + key.value = KEY_NO_VALUE; + } + else + { + key.value = key.defaultValue; + } } } void KeyboardConfig::store() { + config.keys.clear(); + for (auto &key : mKey) { - config.setValue(key.configField, key.value); + if (key.value == key.defaultValue) + continue; + + config.keys[key.configField] = SDL_GetKeyName(key.value); } } @@ -185,7 +198,7 @@ bool KeyboardConfig::hasConflicts() mBindError = strprintf(_("Conflict \"%s\" and \"%s\" keys. " "Resolve them, or gameplay may result" " in strange behaviour."), - mKey[i].caption.c_str(), mKey[j].caption.c_str()); + keyData[i].caption.c_str(), keyData[j].caption.c_str()); return true; } } @@ -199,7 +212,12 @@ void KeyboardConfig::callbackNewKey() mSetupKey->newKeyCallback(mNewKeyIndex); } -int KeyboardConfig::getKeyIndex(int keyValue) const +const std::string &KeyboardConfig::getKeyCaption(int index) const +{ + return keyData[index].caption; +} + +int KeyboardConfig::getKeyIndex(SDL_Keycode keyValue) const { for (int i = 0; i < KEY_TOTAL; i++) { @@ -212,7 +230,7 @@ int KeyboardConfig::getKeyIndex(int keyValue) const } -int KeyboardConfig::getKeyEmoteOffset(int keyValue) const +int KeyboardConfig::getKeyEmoteOffset(SDL_Keycode keyValue) const { for (int i = KEY_EMOTE_1; i <= KEY_EMOTE_12; i++) { diff --git a/src/keyboardconfig.h b/src/keyboardconfig.h index 03f39551..e2d91e29 100644 --- a/src/keyboardconfig.h +++ b/src/keyboardconfig.h @@ -26,6 +26,8 @@ #include <cstdint> #include <string> +#include <SDL.h> + /** * Each key represents a key function. Such as 'Move up', 'Attack' etc. */ @@ -33,8 +35,7 @@ struct KeyFunction { const char* configField; /** Field index that is in the config file. */ int defaultValue; /** The default key value used. */ - std::string caption; /** The caption value for the key function. */ - int value; /** The actual value that is used. */ + SDL_Keycode value; /** The actual value that is used. */ }; class Setup_Keyboard; @@ -93,18 +94,17 @@ class KeyboardConfig /** * Get the key caption, providing more meaning to the user. */ - const std::string &getKeyCaption(int index) const - { return mKey[index].caption; } + const std::string &getKeyCaption(int index) const; /** * Get the key function index by providing the keys value. */ - int getKeyIndex(int keyValue) const; + int getKeyIndex(SDL_Keycode keyValue) const; /** * Get the key function index for an emote by providing the offset value. */ - int getKeyEmoteOffset(int keyValue) const; + int getKeyEmoteOffset(SDL_Keycode keyValue) const; /** * Set the enable flag, which will stop the user from doing actions. @@ -121,7 +121,7 @@ class KeyboardConfig /** * Set the value of the new key. */ - void setNewKey(int value) + void setNewKey(SDL_Keycode value) { mKey[mNewKeyIndex].value = value; } /** diff --git a/src/localplayer.cpp b/src/localplayer.cpp index 7dec601a..7e66632b 100644 --- a/src/localplayer.cpp +++ b/src/localplayer.cpp @@ -29,7 +29,6 @@ #include "map.h" #include "particle.h" #include "playerinfo.h" -#include "sound.h" #include "gui/gui.h" #include "gui/okdialog.h" @@ -63,7 +62,7 @@ LocalPlayer::LocalPlayer(int id, int subtype): mAwayListener = new AwayListener(); - setShowName(config.getValue("showownname", 1)); + setShowName(config.showOwnName); listen(Event::ConfigChannel); listen(Event::ActorSpriteChannel); @@ -870,11 +869,11 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount, msg = N_("Item belongs to someone else."); break; default: msg = N_("Unknown problem picking up item."); break; } - if (config.getValue("showpickupchat", 1)) + if (config.showPickupChat) { serverNotice(_(msg)); } - if (mMap && config.getBoolValue("showpickupparticle")) + if (mMap && config.showPickupParticle) { // Show pickup notification addMessageToQueue(_(msg), UserPalette::PICKUP_INFO); @@ -882,7 +881,7 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount, } else { - if (config.getBoolValue("showpickupchat")) + if (config.showPickupChat) { // TRANSLATORS: This sentence may be translated differently // for different grammatical numbers (singular, plural, ...) @@ -892,7 +891,7 @@ void LocalPlayer::pickedUp(const ItemInfo &itemInfo, int amount, amount, itemInfo.id, itemInfo.name.c_str())); } - if (mMap && config.getBoolValue("showpickupparticle")) + if (mMap && config.showPickupParticle) { // Show pickup notification std::string msg; @@ -1006,7 +1005,7 @@ void LocalPlayer::event(Event::Channel channel, const Event &event) if (event.getType() == Event::ConfigOptionChanged && event.getString("option") == "showownname") { - setShowName(config.getValue("showownname", 1)); + setShowName(config.showOwnName); } } @@ -1020,8 +1019,9 @@ void LocalPlayer::changeAwayMode() if (mAwayMode) { - mAwayDialog = new OkDialog(_("Away"), - config.getValue("afkMessage", "I am away from keyboard")); + auto msg = config.afkMessage.empty() ? _("I am away from keyboard") + : config.afkMessage; + mAwayDialog = new OkDialog(_("Away"), msg); mAwayDialog->addActionListener(mAwayListener); } @@ -1031,33 +1031,31 @@ void LocalPlayer::changeAwayMode() void LocalPlayer::setAway(const std::string &message) { if (!message.empty()) - config.setValue("afkMessage", message); + config.afkMessage = message; changeAwayMode(); } void LocalPlayer::afkRespond(ChatTab *tab, const std::string &nick) { - if (mAwayMode) - { - if (mAfkTimer.passed()) - { - std::string msg = "*AFK*: " - + config.getValue("afkMessage", "I am away from keyboard"); + if (!mAwayMode || !mAfkTimer.passed()) + return; - Net::getChatHandler()->privateMessage(nick, msg); - if (!tab) - { - localChatTab->chatLog(getName() + " : " + msg, - ACT_WHISPER, false); - } - else - { - tab->chatLog(getName(), msg); - } + auto msg = config.afkMessage.empty() ? _("I am away from keyboard") + : config.afkMessage; + msg = strprintf(_("*AFK*: %s"), msg.c_str()); - mAfkTimer.set(AWAY_MESSAGE_TIMEOUT); - } + Net::getChatHandler()->privateMessage(nick, msg); + if (!tab) + { + localChatTab->chatLog(getName() + " : " + msg, + ACT_WHISPER, false); } + else + { + tab->chatLog(getName(), msg); + } + + mAfkTimer.set(AWAY_MESSAGE_TIMEOUT); } void AwayListener::action(const gcn::ActionEvent &event) diff --git a/src/map.cpp b/src/map.cpp index 5d7fa053..929d66f8 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -40,6 +40,7 @@ #include "utils/dtor.h" #include "utils/stringutils.h" +#include <cassert> #include <queue> #include <climits> @@ -326,7 +327,7 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY) // Draw backgrounds drawAmbientLayers(graphics, BACKGROUND_LAYERS, scrollX, scrollY, - config.getIntValue("OverlayDetail")); + config.overlayDetail); // draw the game world for (auto &layer : mLayers) @@ -365,7 +366,7 @@ void Map::draw(Graphics *graphics, int scrollX, int scrollY) } drawAmbientLayers(graphics, FOREGROUND_LAYERS, scrollX, scrollY, - config.getIntValue("OverlayDetail")); + config.overlayDetail); } void Map::drawCollision(Graphics *graphics, int scrollX, int scrollY, @@ -961,7 +962,7 @@ void Map::addParticleEffect(const std::string &effectFile, int x, int y, int w, void Map::initializeParticleEffects(Particle *particleEngine) { - if (config.getBoolValue("particleeffects")) + if (config.particleEffects) { for (auto &particleEffect : particleEffects) { diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp index d8923caa..e1b1a9ea 100644 --- a/src/net/tmwa/generalhandler.cpp +++ b/src/net/tmwa/generalhandler.cpp @@ -43,7 +43,6 @@ #include "net/tmwa/itemhandler.h" #include "net/tmwa/loginhandler.h" #include "net/tmwa/messagein.h" -#include "net/tmwa/messageout.h" #include "net/tmwa/network.h" #include "net/tmwa/npchandler.h" #include "net/tmwa/partyhandler.h" @@ -73,7 +72,7 @@ extern Party *taParty; GeneralHandler::GeneralHandler(): mAdminHandler(new AdminHandler), - mBeingHandler(new BeingHandler(config.getBoolValue("EnableSync"))), + mBeingHandler(new BeingHandler(config.enableSync)), mBuySellHandler(new BuySellHandler), mCharHandler(new CharServerHandler), mChatHandler(new ChatHandler), diff --git a/src/net/tmwa/gui/partytab.cpp b/src/net/tmwa/gui/partytab.cpp index 24a8cc3e..418e0843 100644 --- a/src/net/tmwa/gui/partytab.cpp +++ b/src/net/tmwa/gui/partytab.cpp @@ -147,7 +147,7 @@ bool PartyTab::handleCommand(const std::string &type, const std::string &args) Net::getPartyHandler()->setShareItems(PARTY_SHARE_NO); break; case -1: - chatLog(strprintf(BOOLEAN_OPTIONS, "item")); + chatLog(booleanOptionInstructions("item")); } } else if (type == "exp") @@ -182,7 +182,7 @@ bool PartyTab::handleCommand(const std::string &type, const std::string &args) Net::getPartyHandler()->setShareExperience(PARTY_SHARE_NO); break; case -1: - chatLog(strprintf(BOOLEAN_OPTIONS, "exp")); + chatLog(booleanOptionInstructions("exp")); } } else diff --git a/src/net/tmwa/playerhandler.cpp b/src/net/tmwa/playerhandler.cpp index e4a1815f..f6f6ef41 100644 --- a/src/net/tmwa/playerhandler.cpp +++ b/src/net/tmwa/playerhandler.cpp @@ -322,9 +322,9 @@ void PlayerHandler::handleMessage(MessageIn &msg) if (newMoney > oldMoney) { std::string money = Units::formatCurrency(newMoney - oldMoney); - if (config.getBoolValue("showpickupchat")) + if (config.showPickupChat) serverNotice(strprintf(_("You picked up %s."), money.c_str())); - if (config.getBoolValue("showpickupparticle")) + if (config.showPickupParticle) local_player->addMessageToQueue(money, UserPalette::PICKUP_INFO); } } diff --git a/src/particle.cpp b/src/particle.cpp index aa195c28..754cc43b 100644 --- a/src/particle.cpp +++ b/src/particle.cpp @@ -70,10 +70,10 @@ Particle::~Particle() void Particle::setupEngine() { - Particle::maxCount = config.getIntValue("particleMaxCount"); - Particle::fastPhysics = config.getIntValue("particleFastPhysics"); - Particle::emitterSkip = config.getIntValue("particleEmitterSkip") + 1; - Particle::enabled = config.getBoolValue("particleeffects"); + Particle::maxCount = config.particleMaxCount; + Particle::fastPhysics = config.particleFastPhysics; + Particle::emitterSkip = config.particleEmitterSkip + 1; + Particle::enabled = config.particleEffects; disableAutoDelete(); logger->log("Particle engine set up"); } diff --git a/src/playerrelations.cpp b/src/playerrelations.cpp index 22396009..bec1d081 100644 --- a/src/playerrelations.cpp +++ b/src/playerrelations.cpp @@ -29,57 +29,11 @@ #include "utils/dtor.h" #include "utils/gettext.h" -#define PLAYER_IGNORE_STRATEGY_NOP "nop" -#define DEFAULT_IGNORE_STRATEGY PLAYER_IGNORE_STRATEGY_NOP - -#define NAME "name" // constant for xml serialisation -#define RELATION "relation" // constant for xml serialisation - -// (De)serialisation class -class PlayerConfSerialiser : public ConfigurationListManager<std::pair<std::string, PlayerRelation>, - std::map<std::string, PlayerRelation> *> -{ - ConfigurationObject *writeConfigItem(const std::pair<std::string, PlayerRelation> &value, - ConfigurationObject *cobj) override - { - cobj->setValue(NAME, value.first); - cobj->setValue(RELATION, toString(static_cast<int>(value.second))); - - return cobj; - } - - std::map<std::string, PlayerRelation> * - readConfigItem(ConfigurationObject *cobj, - std::map<std::string, PlayerRelation> *container) override - { - std::string name = cobj->getValue(NAME, std::string()); - if (name.empty()) - return container; - - int v = cobj->getValue(RELATION, static_cast<int>(PlayerRelation::NEUTRAL)); - (*container)[name] = static_cast<PlayerRelation>(v); - - return container; - } -}; - - - PlayerRelationsManager::~PlayerRelationsManager() { delete_all(mIgnoreStrategies); } -void PlayerRelationsManager::clear() -{ - mRelations.clear(); - signalUpdate(); -} - -#define PERSIST_IGNORE_LIST "persistent-player-list" -#define PLAYER_IGNORE_STRATEGY "player-ignore-strategy" -#define DEFAULT_PERMISSIONS "default-player-permissions" - int PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name) { std::vector<PlayerIgnoreStrategy *> &strategies = getPlayerIgnoreStrategies(); @@ -92,43 +46,22 @@ int PlayerRelationsManager::getPlayerIgnoreStrategyIndex(const std::string &name void PlayerRelationsManager::init() { - mPersistIgnores = config.getValue(PERSIST_IGNORE_LIST, 1); - mDefaultPermissions = config.getValue(DEFAULT_PERMISSIONS, mDefaultPermissions); - std::string ignore_strategy_name = config.getValue(PLAYER_IGNORE_STRATEGY, DEFAULT_IGNORE_STRATEGY); - int ignore_strategy_index = getPlayerIgnoreStrategyIndex(ignore_strategy_name); - if (ignore_strategy_index >= 0) - setPlayerIgnoreStrategy(getPlayerIgnoreStrategies()[ignore_strategy_index]); - - mRelations.clear(); + int index = getPlayerIgnoreStrategyIndex(config.playerIgnoreStrategy); + if (index >= 0) + setPlayerIgnoreStrategy(getPlayerIgnoreStrategies()[index]); // Ignores are always saved to the config file, but might not be loaded - if (mPersistIgnores) - { - PlayerConfSerialiser player_conf_serialiser; - config.getList<std::pair<std::string, PlayerRelation>, - std::map<std::string, PlayerRelation> *> - ("player", &mRelations, player_conf_serialiser); - } + if (config.persistentPlayerList) + mRelations = config.players; signalUpdate(); } void PlayerRelationsManager::store() { - PlayerConfSerialiser player_conf_serialiser; - config.setList<std::map<std::string, PlayerRelation>::const_iterator, - std::pair<std::string, PlayerRelation>, - std::map<std::string, PlayerRelation> *> - ("player", - mRelations.begin(), mRelations.end(), - player_conf_serialiser); - - config.setValue(DEFAULT_PERMISSIONS, mDefaultPermissions); - config.setValue(PERSIST_IGNORE_LIST, mPersistIgnores); - config.setValue(PLAYER_IGNORE_STRATEGY, - (mIgnoreStrategy)? mIgnoreStrategy->mShortName : DEFAULT_IGNORE_STRATEGY); - - config.write(); + config.playerIgnoreStrategy = mIgnoreStrategy ? mIgnoreStrategy->mShortName + : DEFAULT_IGNORE_STRATEGY; + config.players = mRelations; } void PlayerRelationsManager::signalUpdate() @@ -143,7 +76,7 @@ unsigned int PlayerRelationsManager::checkPermissionSilently( const std::string &playerName, unsigned int flags) { - unsigned int permissions = mDefaultPermissions; + unsigned int permissions = config.defaultPlayerPermissions; switch (getRelation(playerName)) { @@ -238,12 +171,12 @@ PlayerRelation PlayerRelationsManager::getRelation(const std::string &name) cons unsigned int PlayerRelationsManager::getDefault() const { - return mDefaultPermissions; + return config.defaultPlayerPermissions; } void PlayerRelationsManager::setDefault(unsigned int permissions) { - mDefaultPermissions = permissions; + config.defaultPlayerPermissions = permissions; signalUpdate(); } @@ -258,7 +191,7 @@ public: PIS_nothing() { mDescription = _("Completely ignore"); - mShortName = PLAYER_IGNORE_STRATEGY_NOP; + mShortName = "nop"; } void ignore(Being *being, unsigned int flags) override diff --git a/src/playerrelations.h b/src/playerrelations.h index 2a43675e..38452c2f 100644 --- a/src/playerrelations.h +++ b/src/playerrelations.h @@ -52,6 +52,8 @@ struct PlayerPermissions }; }; +static constexpr const char *DEFAULT_IGNORE_STRATEGY = "nop"; + /** * Ignore strategy: describes how we should handle ignores. */ @@ -178,23 +180,6 @@ public: */ std::vector<std::string> getPlayers() const; - /** - * Removes all recorded player info. - */ - void clear(); - - /** - * Do we persist our `ignore' setup? - */ - bool getPersistIgnores() const { return mPersistIgnores; } - - /** - * Change the `ignore persist' flag. - * - * @param value Whether to persist ignores - */ - void setPersistIgnores(bool value) { mPersistIgnores = value; } - void addListener(PlayerRelationsListener *listener) { mListeners.push_back(listener); @@ -208,9 +193,6 @@ public: private: void signalUpdate(); - bool mPersistIgnores = false; // If NOT set, we delete the ignored data upon reloading - unsigned int mDefaultPermissions = PlayerPermissions::DEFAULT; - PlayerIgnoreStrategy *mIgnoreStrategy = nullptr; std::map<std::string, PlayerRelation> mRelations; std::list<PlayerRelationsListener *> mListeners; diff --git a/src/resources/mapreader.cpp b/src/resources/mapreader.cpp index 3279ba77..b5a5e258 100644 --- a/src/resources/mapreader.cpp +++ b/src/resources/mapreader.cpp @@ -193,7 +193,7 @@ Map *MapReader::readMap(XML::Node node, const std::string &path) } else if (objType == "WARP") { - if (config.getValue("showWarps", 1)) + if (config.showWarps) { map->addParticleEffect( paths.getStringValue("particles") @@ -502,7 +502,7 @@ static Tileset *readTileset(XML::Node node, const std::string &path, Tileset *set = nullptr; std::string pathDir(path); - if (node.hasProperty("source")) + if (node.hasAttribute("source")) { std::string filename = node.getProperty("source", std::string()); filename = resolveRelativePath(path, filename); diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp index 99798ab0..8966f976 100644 --- a/src/resources/settingsmanager.cpp +++ b/src/resources/settingsmanager.cpp @@ -123,7 +123,7 @@ namespace SettingsManager if (node.name() == "monsters") { - if (node.hasProperty("offset")) + if (node.hasAttribute("offset")) { MonsterDB::setMonsterIdOffset(node.getProperty("offset", 0)); } diff --git a/src/resources/theme.cpp b/src/resources/theme.cpp index 29157240..1f7322a6 100644 --- a/src/resources/theme.cpp +++ b/src/resources/theme.cpp @@ -74,7 +74,7 @@ Skin::~Skin() void Skin::updateAlpha(float minimumOpacityAllowed) { const float alpha = std::max(minimumOpacityAllowed, - config.getFloatValue("guialpha")); + config.guiAlpha); mBorder.setAlpha(alpha); @@ -339,7 +339,7 @@ void Theme::prepareThemePath() instance(); // Try theme from settings - if (!tryThemePath(config.getStringValue("theme"))) + if (!tryThemePath(config.theme)) // Try theme from branding if (!tryThemePath(branding.getStringValue("theme"))) // Use default diff --git a/src/resources/userpalette.cpp b/src/resources/userpalette.cpp index 12e4d5bc..55935d8c 100644 --- a/src/resources/userpalette.cpp +++ b/src/resources/userpalette.cpp @@ -27,52 +27,27 @@ #include "utils/gettext.h" #include "utils/stringutils.h" -static const std::string ColorTypeNames[] = { - "ColorBeing", - "ColorPlayer", - "ColorSelf", - "ColorGM", - "ColorNPC", - "ColorMonster", - "ColorParty", - "ColorGuild", - "ColorParticle", - "ColorExperience", - "ColorPickup", - "ColorHitPlayerMonster", - "ColorHitMonsterPlayer", - "ColorHitCritical", - "ColorHitLocalPlayerMonster", - "ColorHitLocalPlayerCritical", - "ColorHitLocalPlayerMiss", - "ColorMiss" +static constexpr const char *ColorTypeNames[] = { + "Being", + "Player", + "Self", + "GM", + "NPC", + "Monster", + "Party", + "Guild", + "Particle", + "Experience", + "Pickup", + "HitPlayerMonster", + "HitMonsterPlayer", + "HitCritical", + "HitLocalPlayerMonster", + "HitLocalPlayerCritical", + "HitLocalPlayerMiss", + "Miss" }; -std::string UserPalette::getConfigName(const std::string &typeName) -{ - std::string res = "Color" + typeName; - - int pos = 5; - for (size_t i = 0; i < typeName.length(); i++) - { - if (i == 0 || typeName[i] == '_') - { - if (i > 0) - i++; - - res[pos] = typeName[i]; - } - else - { - res[pos] = tolower(typeName[i]); - } - pos++; - } - res.erase(pos, res.length() - pos); - - return res; -} - UserPalette::UserPalette(): Palette(USER_COLOR_LAST) { @@ -110,20 +85,20 @@ UserPalette::UserPalette(): UserPalette::~UserPalette() { + config.colors.clear(); + + // TODO: Don't write out colors when they have the default value for (auto &color : mColors) { - const std::string &configName = ColorTypeNames[color.type]; - config.setValue(configName + "Gradient", color.committedGrad); + auto &configColor = config.colors[ColorTypeNames[color.type]]; - if (color.grad != STATIC) - config.setValue(configName + "Delay", color.delay); + configColor.gradient = color.committedGrad; + + if (color.grad != STATIC && color.delay != GRADIENT_DELAY) + configColor.delay = color.delay; if (color.grad == STATIC || color.grad == PULSE) - { - char buffer[20]; - snprintf(buffer, 20, "0x%06x", color.getRGB()); - config.setValue(configName, std::string(buffer)); - } + configColor.color = strprintf("0x%06x", color.getRGB()); } } @@ -215,23 +190,19 @@ int UserPalette::getColorTypeAt(int i) return mColors[i].type; } -void UserPalette::addColor(int type, int rgb, Palette::GradientType grad, +void UserPalette::addColor(int type, unsigned rgb, GradientType grad, const std::string &text, int delay) { - const std::string &configName = ColorTypeNames[type]; - char buffer[20]; - snprintf(buffer, 20, "0x%06x", rgb); - const std::string rgbString = config.getValue(configName, - std::string(buffer)); - unsigned int rgbValue = 0; - if (rgbString.length() == 8 && rgbString[0] == '0' && rgbString[1] == 'x') - rgbValue = atox(rgbString); - else - rgbValue = atoi(rgbString.c_str()); - gcn::Color trueCol = rgbValue; - grad = (GradientType) config.getValue(configName + "Gradient", grad); - delay = (int) config.getValue(configName + "Delay", delay); - mColors[type].set(type, trueCol, grad, delay); + auto colorIt = config.colors.find(ColorTypeNames[type]); + if (colorIt != config.colors.end()) + { + const UserColor &userColor = colorIt->second; + rgb = atox(userColor.color); + grad = static_cast<GradientType>(userColor.gradient); + delay = userColor.delay.value_or(GRADIENT_DELAY); + } + + mColors[type].set(type, gcn::Color(rgb), grad, delay); mColors[type].text = text; if (grad != STATIC) diff --git a/src/resources/userpalette.h b/src/resources/userpalette.h index 6eba44b2..946a4725 100644 --- a/src/resources/userpalette.h +++ b/src/resources/userpalette.h @@ -175,24 +175,12 @@ class UserPalette : public Palette, public gcn::ListModel void commit(bool commitNonStatic); /** - * Prefixes the given string with "Color", lowercases all letters but - * the first and all following a '_'. All '_'s will be removed. - * - * E.g.: HIT_PLAYER_MONSTER -> HitPlayerMonster - * - * @param typeName string to transform - * - * @return the transformed string - */ - static std::string getConfigName(const std::string &typeName); - - /** * Initialise color * * @param rgb default color if not found in config * @param text identifier of color */ - void addColor(int type, int rgb, GradientType grad, + void addColor(int type, unsigned int rgb, GradientType grad, const std::string &text, int delay = GRADIENT_DELAY); }; diff --git a/src/text.cpp b/src/text.cpp index 26124666..e3776410 100644 --- a/src/text.cpp +++ b/src/text.cpp @@ -54,7 +54,7 @@ Text::Text(const std::string &text, int x, int y, { textManager = new TextManager; Image *sbImage = Theme::getImageFromTheme("bubble.png|W:#" - + config.getStringValue("speechBubblecolor")); + + config.speechBubblecolor); mBubble.grid[0] = sbImage->getSubImage(0, 0, 5, 5); mBubble.grid[1] = sbImage->getSubImage(5, 0, 5, 5); mBubble.grid[2] = sbImage->getSubImage(10, 0, 5, 5); @@ -65,9 +65,8 @@ Text::Text(const std::string &text, int x, int y, mBubble.grid[7] = sbImage->getSubImage(5, 10, 5, 5); mBubble.grid[8] = sbImage->getSubImage(10, 10, 5, 5); mBubbleArrow = sbImage->getSubImage(0, 15, 15, 10); - const float bubbleAlpha = config.getFloatValue("speechBubbleAlpha"); - mBubble.setAlpha(bubbleAlpha); - mBubbleArrow->setAlpha(bubbleAlpha); + mBubble.setAlpha(config.speechBubbleAlpha); + mBubbleArrow->setAlpha(config.speechBubbleAlpha); sbImage->decRef(); } ++mInstances; diff --git a/src/utils/stringutils.h b/src/utils/stringutils.h index d6c45474..e7ff1332 100644 --- a/src/utils/stringutils.h +++ b/src/utils/stringutils.h @@ -22,8 +22,9 @@ #ifndef UTILS_STRINGUTILS_H #define UTILS_STRINGUTILS_H -#include <string> +#include <optional> #include <sstream> +#include <string> #include <vector> /** @@ -144,6 +145,55 @@ std::string findSameSubstring(const std::string &str1, */ bool getBoolFromString(std::string text, bool def = false); +inline void fromString(const char *str, std::string &value) +{ + value = str; +} + +inline void fromString(const char *str, int &value) +{ + value = atoi(str); +} + +inline void fromString(const char *str, unsigned &value) +{ + value = strtoul(str, nullptr, 10); +} + +inline void fromString(const char *str, unsigned short &value) +{ + value = static_cast<unsigned short>(strtoul(str, nullptr, 10)); +} + +inline void fromString(const char *str, float &value) +{ + value = strtof(str, nullptr); +} + +inline void fromString(const char *str, double &value) +{ + value = atof(str); +} + +inline void fromString(const char *str, bool &value) +{ + value = getBoolFromString(str); +} + +template<typename Enum, std::enable_if_t<std::is_enum_v<Enum>, bool> = true> +inline void fromString(const char *str, Enum &value) +{ + value = static_cast<Enum>(atoi(str)); +} + +template<typename T> +inline void fromString(const char *str, std::optional<T> &value) +{ + T v; + fromString(str, v); + value = v; +} + /** * Returns the most approaching string of base from candidates. */ diff --git a/src/utils/xml.h b/src/utils/xml.h index 95f7be99..13c06988 100644 --- a/src/utils/xml.h +++ b/src/utils/xml.h @@ -47,7 +47,10 @@ namespace XML std::string_view name() const { return (const char *) node->name; } std::string_view textContent() const; - bool hasProperty(const char *name) const; + template<typename T> + bool attribute(const char *name, T &value); + + bool hasAttribute(const char *name) const; int getProperty(const char *name, int def) const; double getFloatProperty(const char *name, double def) const; std::string getProperty(const char *name, const std::string &def) const; @@ -98,45 +101,58 @@ namespace XML return {}; } - inline bool Node::hasProperty(const char *name) const + inline const char *Node::attribute(const char *name) const { - return xmlHasProp(node, BAD_CAST name) != nullptr; + if (node->type != XML_ELEMENT_NODE) + return nullptr; + + for (xmlAttrPtr prop = node->properties; prop; prop = prop->next) { + if (xmlStrEqual(prop->name, BAD_CAST name)) { + if (prop->children) + return reinterpret_cast<const char*>(prop->children->content); + else + return nullptr; + } + } + return nullptr; } - inline int Node::getProperty(const char *name, int def) const + template<typename T> + inline bool Node::attribute(const char *name, T &value) { - int ret = def; - - if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) + if (const char *str = attribute(name)) { - ret = atol((char*)prop); - xmlFree(prop); + fromString(str, value); + return true; } + return false; + } + inline bool Node::hasAttribute(const char *name) const + { + return attribute(name) != nullptr; + } + + inline int Node::getProperty(const char *name, int def) const + { + int ret = def; + if (const char *str = attribute(name)) + fromString(str, ret); return ret; } inline double Node::getFloatProperty(const char *name, double def) const { double ret = def; - - if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) - { - ret = atof((char*)prop); - xmlFree(prop); - } - + if (const char *str = attribute(name)) + fromString(str, ret); return ret; } inline std::string Node::getProperty(const char *name, const std::string &def) const { - if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) - { - std::string val = (char*)prop; - xmlFree(prop); - return val; - } + if (const char *str = attribute(name)) + return str; return def; } @@ -144,12 +160,8 @@ namespace XML inline bool Node::getBoolProperty(const char *name, bool def) const { bool ret = def; - - if (xmlChar *prop = xmlGetProp(node, BAD_CAST name)) - { - ret = getBoolFromString((char*) prop, def); - xmlFree(prop); - } + if (const char *str = attribute(name)) + ret = getBoolFromString(str, def); return ret; } |