summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/being.cpp12
-rw-r--r--src/chatlogger.cpp4
-rw-r--r--src/client.cpp110
-rw-r--r--src/client.h5
-rw-r--r--src/commandhandler.cpp19
-rw-r--r--src/commandhandler.h3
-rw-r--r--src/configuration.cpp451
-rw-r--r--src/configuration.h262
-rw-r--r--src/defaults.cpp65
-rw-r--r--src/defaults.h1
-rw-r--r--src/emoteshortcut.cpp13
-rw-r--r--src/event.h2
-rw-r--r--src/game.cpp2
-rw-r--r--src/gui/chatwindow.cpp7
-rw-r--r--src/gui/chatwindow.h12
-rw-r--r--src/gui/customserverdialog.cpp2
-rw-r--r--src/gui/customserverdialog.h2
-rw-r--r--src/gui/emotepopup.cpp4
-rw-r--r--src/gui/gui.cpp6
-rw-r--r--src/gui/minimap.cpp14
-rw-r--r--src/gui/minimap.h1
-rw-r--r--src/gui/ministatuswindow.cpp4
-rw-r--r--src/gui/npcdialog.cpp20
-rw-r--r--src/gui/npcdialog.h8
-rw-r--r--src/gui/outfitwindow.cpp79
-rw-r--r--src/gui/outfitwindow.h9
-rw-r--r--src/gui/palette.h2
-rw-r--r--src/gui/serverdialog.cpp79
-rw-r--r--src/gui/setup_audio.cpp36
-rw-r--r--src/gui/setup_interface.cpp73
-rw-r--r--src/gui/setup_joystick.cpp6
-rw-r--r--src/gui/setup_keyboard.h2
-rw-r--r--src/gui/setup_players.cpp67
-rw-r--r--src/gui/setup_players.h5
-rw-r--r--src/gui/setup_video.cpp70
-rw-r--r--src/gui/updaterwindow.cpp2
-rw-r--r--src/gui/viewport.cpp41
-rw-r--r--src/gui/viewport.h4
-rw-r--r--src/gui/widgets/button.cpp2
-rw-r--r--src/gui/widgets/chattab.cpp4
-rw-r--r--src/gui/widgets/checkbox.cpp2
-rw-r--r--src/gui/widgets/dropdown.cpp2
-rw-r--r--src/gui/widgets/emoteshortcutcontainer.cpp6
-rw-r--r--src/gui/widgets/itemshortcutcontainer.cpp6
-rw-r--r--src/gui/widgets/listbox.cpp2
-rw-r--r--src/gui/widgets/playerbox.cpp7
-rw-r--r--src/gui/widgets/progressbar.cpp2
-rw-r--r--src/gui/widgets/radiobutton.cpp4
-rw-r--r--src/gui/widgets/resizegrip.cpp4
-rw-r--r--src/gui/widgets/scrollarea.cpp10
-rw-r--r--src/gui/widgets/shoplistbox.cpp7
-rw-r--r--src/gui/widgets/shoplistbox.h2
-rw-r--r--src/gui/widgets/slider.cpp2
-rw-r--r--src/gui/widgets/tab.cpp2
-rw-r--r--src/gui/widgets/table.cpp4
-rw-r--r--src/gui/widgets/textfield.cpp4
-rw-r--r--src/gui/widgets/textpreview.cpp4
-rw-r--r--src/gui/widgets/window.cpp79
-rw-r--r--src/gui/widgets/window.h4
-rw-r--r--src/itemshortcut.cpp45
-rw-r--r--src/joystick.cpp29
-rw-r--r--src/keyboardconfig.cpp166
-rw-r--r--src/keyboardconfig.h14
-rw-r--r--src/localplayer.cpp54
-rw-r--r--src/map.cpp7
-rw-r--r--src/net/tmwa/generalhandler.cpp3
-rw-r--r--src/net/tmwa/gui/partytab.cpp4
-rw-r--r--src/net/tmwa/playerhandler.cpp4
-rw-r--r--src/particle.cpp8
-rw-r--r--src/playerrelations.cpp91
-rw-r--r--src/playerrelations.h22
-rw-r--r--src/resources/mapreader.cpp4
-rw-r--r--src/resources/settingsmanager.cpp2
-rw-r--r--src/resources/theme.cpp4
-rw-r--r--src/resources/userpalette.cpp107
-rw-r--r--src/resources/userpalette.h14
-rw-r--r--src/text.cpp7
-rw-r--r--src/utils/stringutils.h52
-rw-r--r--src/utils/xml.h68
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 &currentServer, 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 &currentServer, 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 &currentServer, 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;
}