summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--AUTHORS1
-rw-r--r--mana.cbp4
-rw-r--r--mana.files4
-rw-r--r--src/CMakeLists.txt4
-rw-r--r--src/client.cpp20
-rw-r--r--src/net/manaserv/generalhandler.cpp10
-rw-r--r--src/net/tmwa/generalhandler.cpp14
-rw-r--r--src/resources/attributes.cpp188
-rw-r--r--src/resources/attributes.h13
-rw-r--r--src/resources/emotedb.cpp116
-rw-r--r--src/resources/emotedb.h9
-rw-r--r--src/resources/hairdb.cpp79
-rw-r--r--src/resources/hairdb.h12
-rw-r--r--src/resources/monsterdb.cpp188
-rw-r--r--src/resources/monsterdb.h10
-rw-r--r--src/resources/npcdb.cpp71
-rw-r--r--src/resources/npcdb.h11
-rw-r--r--src/resources/settingsmanager.cpp191
-rw-r--r--src/resources/settingsmanager.h35
-rw-r--r--src/resources/specialdb.cpp71
-rw-r--r--src/resources/specialdb.h9
-rw-r--r--src/statuseffect.cpp82
-rw-r--r--src/statuseffect.h9
-rw-r--r--src/units.cpp107
-rw-r--r--src/units.h10
-rw-r--r--src/utils/path.cpp153
-rw-r--r--src/utils/path.h42
27 files changed, 913 insertions, 550 deletions
diff --git a/AUTHORS b/AUTHORS
index 031495a5..83a31805 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -42,6 +42,7 @@ Marcel W. Wysocki <maci satgnu.org>
Mateusz Kaduk (Usiu) <mateusz.kaduk gmail.com>
Matthias Hartmann <hartmann.matthias gmail.com>
Philipp Sehmisch (Crush) <tmw crushnet.org>
+Przemysław Grzywacz <nexather gmail.com>
Roderic Morris (rodge) <roderic ccs.neu.edu>
Rogier Polak <rogier.l.a.polak gmail.com>
Scott Ellis <quiche_on_a_leash hotmail.co.uk>
diff --git a/mana.cbp b/mana.cbp
index f25a33c4..3d5345d7 100644
--- a/mana.cbp
+++ b/mana.cbp
@@ -552,6 +552,8 @@
<Unit filename="src\resources\resource.h" />
<Unit filename="src\resources\resourcemanager.cpp" />
<Unit filename="src\resources\resourcemanager.h" />
+ <Unit filename="src\resources\settingsmanager.cpp" />
+ <Unit filename="src\resources\settingsmanager.h" />
<Unit filename="src\resources\soundeffect.cpp" />
<Unit filename="src\resources\soundeffect.h" />
<Unit filename="src\resources\specialdb.cpp" />
@@ -598,6 +600,8 @@
<Unit filename="src\utils\physfsrwops.c">
<Option compilerVar="CC" />
</Unit>
+ <Unit filename="src\utils\path.cpp" />
+ <Unit filename="src\utils\path.h" />
<Unit filename="src\utils\physfsrwops.h" />
<Unit filename="src\utils\sha256.cpp" />
<Unit filename="src\utils\sha256.h" />
diff --git a/mana.files b/mana.files
index dbfddc00..16a0a9a6 100644
--- a/mana.files
+++ b/mana.files
@@ -499,6 +499,8 @@ src/resources/resource.cpp
src/resources/resource.h
src/resources/resourcemanager.cpp
src/resources/resourcemanager.h
+src/resources/settingsmanager.cpp
+src/resources/settingsmanager.h
src/resources/soundeffect.cpp
src/resources/soundeffect.h
src/resources/specialdb.cpp
@@ -542,6 +544,8 @@ src/utils/mathutils.h
src/utils/mkdir.cpp
src/utils/mkdir.h
src/utils/mutex.h
+src/utils/path.cpp
+src/utils/path.h
src/utils/physfsrwops.c
src/utils/physfsrwops.h
src/utils/sha256.cpp
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 946f4ba6..6c0b3081 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -399,6 +399,8 @@ SET(SRCS
resources/resource.h
resources/resourcemanager.cpp
resources/resourcemanager.h
+ resources/settingsmanager.cpp
+ resources/settingsmanager.h
resources/soundeffect.h
resources/soundeffect.cpp
resources/specialdb.cpp
@@ -418,6 +420,8 @@ SET(SRCS
utils/dtor.h
utils/gettext.h
utils/mathutils.h
+ utils/path.cpp
+ utils/path.h
utils/physfsrwops.c
utils/physfsrwops.h
utils/sha256.cpp
diff --git a/src/client.cpp b/src/client.cpp
index e6ab9191..0d2c4bca 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -75,6 +75,7 @@
#include "resources/resourcemanager.h"
#include "resources/theme.h"
#include "resources/userpalette.h"
+#include "resources/settingsmanager.h"
#include "utils/gettext.h"
#include "utils/mkdir.h"
@@ -452,13 +453,9 @@ Client::~Client()
SDL_RemoveTimer(mSecondsCounterId);
// Unload XML databases
+ SettingsManager::unload();
CharDB::unload();
- hairDB.unload();
- EmoteDB::unload();
delete itemDb;
- MonsterDB::unload();
- NPCDB::unload();
- StatusEffect::unload();
// Before config.write() since it writes the shortcuts to the config
delete itemShortcut;
@@ -761,11 +758,16 @@ int Client::exec()
// Read default paths file 'data/paths.xml'
paths.init("paths.xml", true);
+ // TODO remove this as soon as inventoryhandler stops using this event
Event::trigger(Event::ClientChannel, Event::LoadingDatabases);
+ // load game settings
+
+
// Load XML databases
+ SettingsManager::load();
+
CharDB::load();
- hairDB.load();
switch (Net::getNetworkType())
{
case ServerInfo::TMWATHENA:
@@ -790,12 +792,6 @@ int Client::exec()
STATE_CHOOSE_SERVER);
break;
}
- MonsterDB::load();
- SpecialDB::load();
- NPCDB::load();
- EmoteDB::load();
- StatusEffect::load();
- Units::loadUnits();
ActorSprite::load();
diff --git a/src/net/manaserv/generalhandler.cpp b/src/net/manaserv/generalhandler.cpp
index c6b2af18..1e39410c 100644
--- a/src/net/manaserv/generalhandler.cpp
+++ b/src/net/manaserv/generalhandler.cpp
@@ -133,10 +133,6 @@ void GeneralHandler::reload()
netToken.clear();
gameServer.clear();
chatServer.clear();
-
- Attributes::unload();
- Attributes::load();
- Attributes::informItemDB();
}
void GeneralHandler::unload()
@@ -154,7 +150,6 @@ void GeneralHandler::unload()
delete gameServerConnection;
delete chatServerConnection;
- Attributes::unload();
finalize();
}
@@ -190,11 +185,6 @@ void GeneralHandler::event(Event::Channel channel,
game->gameLoading();
}
}
- else if (event.getType() == Event::LoadingDatabases)
- {
- Attributes::load();
- Attributes::informItemDB();
- }
}
else if (channel == Event::GameChannel)
{
diff --git a/src/net/tmwa/generalhandler.cpp b/src/net/tmwa/generalhandler.cpp
index 0ce16691..5e445eaf 100644
--- a/src/net/tmwa/generalhandler.cpp
+++ b/src/net/tmwa/generalhandler.cpp
@@ -186,17 +186,12 @@ void GeneralHandler::reload()
static_cast<LoginHandler*>(mLoginHandler.get())->clearWorlds();
static_cast<CharServerHandler*>(mCharHandler.get())->setCharCreateDialog(0);
static_cast<CharServerHandler*>(mCharHandler.get())->setCharSelectDialog(0);
-
- Attributes::unload();
- Attributes::load();
}
void GeneralHandler::unload()
{
if (mNetwork)
mNetwork->clearHandlers();
-
- Attributes::unload();
}
void GeneralHandler::flushNetwork()
@@ -226,14 +221,7 @@ void GeneralHandler::clearHandlers()
void GeneralHandler::event(Event::Channel channel,
const Event &event)
{
- if (channel == Event::ClientChannel)
- {
- if (event.getType() == Event::LoadingDatabases)
- {
- Attributes::load();
- }
- }
- else if (channel == Event::GameChannel)
+ if (channel == Event::GameChannel)
{
if (event.getType() == Event::GuiWindowsLoaded)
{
diff --git a/src/resources/attributes.cpp b/src/resources/attributes.cpp
index c4c67fba..58bff6f1 100644
--- a/src/resources/attributes.cpp
+++ b/src/resources/attributes.cpp
@@ -29,7 +29,6 @@
#include "utils/gettext.h"
#include "utils/stringutils.h"
-#include "utils/xml.h"
#include <list>
#include <map>
@@ -238,120 +237,121 @@ namespace Attributes {
}
}
- void load()
+ void init()
{
- logger->log("Initializing attributes database...");
+ if (attributes.size())
+ unload();
+ }
- XML::Document doc(DEFAULT_ATTRIBUTESDB_FILE);
- xmlNodePtr rootNode = doc.rootNode();
+ /**
+ * Read attribute node
+ */
+ void readAttributeNode(xmlNodePtr node, const std::string &filename)
+ {
+ int id = XML::getProperty(node, "id", 0);
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "attributes"))
+ if (!id)
{
- logger->log("Attributes: Error while loading "
- DEFAULT_ATTRIBUTESDB_FILE ". Using Built-ins.");
- loadBuiltins();
- fillLabels();
+ logger->log("Attributes: Invalid or missing stat ID in "
+ DEFAULT_ATTRIBUTESDB_FILE "!");
return;
}
+ else if (attributes.find(id) != attributes.end())
+ {
+ logger->log("Attributes: Redefinition of stat ID %d", id);
+ }
+
+ std::string name = XML::getProperty(node, "name", "");
- for_each_xml_child_node(node, rootNode)
+ if (name.empty())
{
- if (xmlStrEqual(node->name, BAD_CAST "attribute"))
- {
- int id = XML::getProperty(node, "id", 0);
+ logger->log("Attributes: Invalid or missing stat name in "
+ DEFAULT_ATTRIBUTESDB_FILE "!");
+ return;
+ }
+
+ // Create the attribute.
+ Attribute a;
+ a.id = id;
+ a.name = name;
+ a.description = XML::getProperty(node, "desc", "");
+ a.modifiable = XML::getBoolProperty(node, "modifiable", false);
+ a.scope = XML::getProperty(node, "scope", "none");
+ a.playerInfoId = getPlayerInfoIdFromAttrType(
+ XML::getProperty(node, "player-info", ""));
+
+ attributes[id] = a;
- if (!id)
+ unsigned int count = 0;
+ for_each_xml_child_node(effectNode, node)
+ {
+ if (!xmlStrEqual(effectNode->name, BAD_CAST "modifier"))
+ continue;
+ ++count;
+ std::string tag = XML::getProperty(effectNode, "tag", "");
+ if (tag.empty())
+ {
+ if (name.empty())
{
- logger->log("Attributes: Invalid or missing stat ID in "
- DEFAULT_ATTRIBUTESDB_FILE "!");
+ logger->log("Attribute modifier in attribute %u:%s: "
+ "Empty name definition "
+ "on empty tag definition, skipping.",
+ a.id, a.name.c_str());
+ --count;
continue;
}
- else if (attributes.find(id) != attributes.end())
- {
- logger->log("Attributes: Redefinition of stat ID %d", id);
- }
-
- std::string name = XML::getProperty(node, "name", "");
+ tag = name.substr(0, name.size() > 3 ? 3 : name.size());
+ tag = toLower(tag) + toString(count);
+ }
+ std::string effect = XML::getProperty(effectNode, "effect", "");
+ if (effect.empty())
+ {
if (name.empty())
{
- logger->log("Attributes: Invalid or missing stat name in "
- DEFAULT_ATTRIBUTESDB_FILE "!");
+ logger->log("Attribute modifier in attribute %u:%s: "
+ "Empty name definition "
+ "on empty effect definition, skipping.",
+ a.id, a.name.c_str());
+ --count;
continue;
}
+ else
+ effect = name + " %+f";
+ }
+ tags.insert(std::make_pair(tag, effect));
+ }
+ logger->log("Found %d tags for attribute %d.", count, id);
- // Create the attribute.
- Attribute a;
- a.id = id;
- a.name = name;
- a.description = XML::getProperty(node, "desc", "");
- a.modifiable = XML::getBoolProperty(node, "modifiable", false);
- a.scope = XML::getProperty(node, "scope", "none");
- a.playerInfoId = getPlayerInfoIdFromAttrType(
- XML::getProperty(node, "player-info", ""));
-
- attributes[id] = a;
-
- unsigned int count = 0;
- for_each_xml_child_node(effectNode, node)
- {
- if (!xmlStrEqual(effectNode->name, BAD_CAST "modifier"))
- continue;
- ++count;
- std::string tag = XML::getProperty(effectNode, "tag", "");
- if (tag.empty())
- {
- if (name.empty())
- {
- logger->log("Attribute modifier in attribute %u:%s: "
- "Empty name definition "
- "on empty tag definition, skipping.",
- a.id, a.name.c_str());
- --count;
- continue;
- }
- tag = name.substr(0, name.size() > 3 ? 3 : name.size());
- tag = toLower(tag) + toString(count);
- }
-
- std::string effect = XML::getProperty(effectNode, "effect", "");
- if (effect.empty())
- {
- if (name.empty())
- {
- logger->log("Attribute modifier in attribute %u:%s: "
- "Empty name definition "
- "on empty effect definition, skipping.",
- a.id, a.name.c_str());
- --count;
- continue;
- }
- else
- effect = name + " %+f";
- }
- tags.insert(std::make_pair(tag, effect));
- }
- logger->log("Found %d tags for attribute %d.", count, id);
-
- }// End attribute
- else if (xmlStrEqual(node->name, BAD_CAST "points"))
- {
- creationPoints = XML::getProperty(node, "start",DEFAULT_POINTS);
- attributeMinimum = XML::getProperty(node, "minimum",
- DEFAULT_MIN_PTS);
- attributeMaximum = XML::getProperty(node, "maximum",
- DEFAULT_MAX_PTS);
- logger->log("Loaded points: start: %i, min: %i, max: %i.",
- creationPoints, attributeMinimum, attributeMaximum);
- }
- else
- {
- continue;
- }
- }
+ }
+
+ /**
+ * Read points node
+ */
+ void readPointsNode(xmlNodePtr node, const std::string &filename)
+ {
+ creationPoints = XML::getProperty(node, "start",DEFAULT_POINTS);
+ attributeMinimum = XML::getProperty(node, "minimum",
+ DEFAULT_MIN_PTS);
+ attributeMaximum = XML::getProperty(node, "maximum",
+ DEFAULT_MAX_PTS);
+ logger->log("Loaded points: start: %i, min: %i, max: %i.",
+ creationPoints, attributeMinimum, attributeMaximum);
+ }
+
+ /**
+ * Check if all the data loaded by readPointsNode and readAttributeNode is ok
+ */
+ void checkStatus()
+ {
logger->log("Found %d tags for %d attributes.", int(tags.size()),
int(attributes.size()));
+ if (attributes.size() == 0)
+ {
+ loadBuiltins();
+ }
+
fillLabels();
// Sanity checks on starting points
diff --git a/src/resources/attributes.h b/src/resources/attributes.h
index 7124ba94..41093af2 100644
--- a/src/resources/attributes.h
+++ b/src/resources/attributes.h
@@ -24,9 +24,18 @@
#include <string>
#include <vector>
-namespace Attributes {
+#include "utils/xml.h"
- void load();
+namespace Attributes
+{
+
+ void init();
+
+ void readAttributeNode(xmlNodePtr node, const std::string &filename);
+
+ void readPointsNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
void unload();
diff --git a/src/resources/emotedb.cpp b/src/resources/emotedb.cpp
index 00721ac4..04dd4bbb 100644
--- a/src/resources/emotedb.cpp
+++ b/src/resources/emotedb.cpp
@@ -1,7 +1,7 @@
/*
* Emote database
* Copyright (C) 2009 Aethyra Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -29,8 +29,6 @@
#include "resources/image.h"
#include "resources/imageset.h"
-#include "utils/xml.h"
-
namespace
{
Emotes mEmotes;
@@ -39,7 +37,7 @@ namespace
int mLastEmote = 0;
}
-void EmoteDB::load()
+void EmoteDB::init()
{
if (mLoaded)
unload();
@@ -51,74 +49,66 @@ void EmoteDB::load()
mLastEmote = 0;
- logger->log("Initializing emote database...");
+}
+
+void EmoteDB::readEmoteNode(xmlNodePtr node, const std::string &filename)
+{
+ int id = XML::getProperty(node, "id", -1);
+ if (id == -1)
+ {
+ logger->log("Emote Database: Emote with missing ID in %s!", filename.c_str());
+ return;
+ }
+
+ Emote *currentEmote = new Emote;
+
+ currentEmote->name = XML::getProperty(node, "name", "unknown");
+ currentEmote->effect = XML::getProperty(node, "effectid", -1);
+
+ if (currentEmote->effect == -1)
+ {
+ logger->log("Emote Database: Warning: Emote %s has no attached effect in %s!",
+ currentEmote->name.c_str(), filename.c_str());
+ delete currentEmote;
+ return;
+ }
- XML::Document doc("emotes.xml");
- xmlNodePtr rootNode = doc.rootNode();
+ const std::string imageName = XML::getProperty(node, "image", "");
+ const int width = XML::getProperty(node, "width", 0);
+ const int height = XML::getProperty(node, "height", 0);
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "emotes"))
+ if (imageName.empty() || width <= 0 || height <= 0)
{
- logger->log("Emote Database: Error while loading emotes.xml!");
+ logger->log("Emote Database: Warning: Emote %s has bad imageset values in %s",
+ currentEmote->name.c_str(), filename.c_str());
+ delete currentEmote;
return;
}
- //iterate <emote>s
- for_each_xml_child_node(emoteNode, rootNode)
+ ImageSet *is = ResourceManager::getInstance()->getImageSet(imageName,
+ width,
+ height);
+ if (!is || !(is->size() > 0))
+ {
+ logger->log("Emote Database: Error loading imageset for emote %s in %s",
+ currentEmote->name.c_str(), filename.c_str());
+ delete is;
+ delete currentEmote;
+ return;
+ }
+ else
{
- if (!xmlStrEqual(emoteNode->name, BAD_CAST "emote"))
- continue;
-
- int id = XML::getProperty(emoteNode, "id", -1);
- if (id == -1)
- {
- logger->log("Emote Database: Emote with missing ID in emotes.xml!");
- continue;
- }
-
- Emote *currentEmote = new Emote;
-
- currentEmote->name = XML::getProperty(emoteNode, "name", "unknown");
- currentEmote->effect = XML::getProperty(emoteNode, "effectid", -1);
-
- if (currentEmote->effect == -1)
- {
- logger->log("Emote Database: Warning: Emote with no attached effect!");
- delete currentEmote;
- continue;
- }
-
- const std::string imageName = XML::getProperty(emoteNode, "image", "");
- const int width = XML::getProperty(emoteNode, "width", 0);
- const int height = XML::getProperty(emoteNode, "height", 0);
-
- if (imageName.empty() || width <= 0 || height <= 0)
- {
- logger->log("Emote Database: Warning: Emote with bad imageset values");
- delete currentEmote;
- continue;
- }
-
- ImageSet *is = ResourceManager::getInstance()->getImageSet(imageName,
- width,
- height);
- if (!is || !(is->size() > 0))
- {
- logger->log("Emote Database: Error loading imageset");
- delete is;
- delete currentEmote;
- continue;
- }
- else
- {
- // For now we just use the first image in the animation
- currentEmote->sprite = new ImageSprite(is->get(0));
- }
-
- mEmotes[id] = currentEmote;
- if (id > mLastEmote)
- mLastEmote = id;
+ // For now we just use the first image in the animation
+ currentEmote->sprite = new ImageSprite(is->get(0));
}
+ mEmotes[id] = currentEmote;
+ if (id > mLastEmote)
+ mLastEmote = id;
+}
+
+void EmoteDB::checkStatus()
+{
mLoaded = true;
}
diff --git a/src/resources/emotedb.h b/src/resources/emotedb.h
index a1e991ec..33195d82 100644
--- a/src/resources/emotedb.h
+++ b/src/resources/emotedb.h
@@ -1,7 +1,7 @@
/*
* Emote database
* Copyright (C) 2009 Aethyra Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -25,6 +25,7 @@
#include <list>
#include <map>
#include <string>
+#include "utils/xml.h"
class ImageSprite;
@@ -42,7 +43,11 @@ typedef std::map<int, Emote*> Emotes;
*/
namespace EmoteDB
{
- void load();
+ void init();
+
+ void readEmoteNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
void unload();
diff --git a/src/resources/hairdb.cpp b/src/resources/hairdb.cpp
index 26ad966e..2e9747a2 100644
--- a/src/resources/hairdb.cpp
+++ b/src/resources/hairdb.cpp
@@ -1,7 +1,7 @@
/*
* Hair database
* Copyright (C) 2008 Aethyra Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -23,58 +23,32 @@
#include "log.h"
-#include "utils/xml.h"
-
#include <assert.h>
#define COLOR_WHITE "#ffffff"
-#define HAIR_XML_FILE "hair.xml"
-void HairDB::load()
+
+void HairDB::init()
{
if (mLoaded)
unload();
// Default entry
mHairColors[0] = COLOR_WHITE;
+}
- XML::Document *doc = new XML::Document(HAIR_XML_FILE);
- xmlNodePtr root = doc->rootNode();
-
- if (!root || (!xmlStrEqual(root->name, BAD_CAST "colors")
- && !xmlStrEqual(root->name, BAD_CAST "hair")))
- {
- logger->log("HairDb: Failed to find any old <colors> or new "
- "<hair> nodes.");
- delete doc;
- mLoaded = true;
- return;
- }
+void HairDB::readHairColorNode(xmlNodePtr node, const std::string &filename)
+{
+ int id = XML::getProperty(node, "id", 0);
- // Old colors.xml file style. The hair style will be declared
- // in the items.xml file.
- if (xmlStrEqual(root->name, BAD_CAST "colors"))
- {
- loadHairColorsNode(root);
- }
- else if (xmlStrEqual(root->name, BAD_CAST "hair"))
- {
- // Loading new format: hair styles + colors.
- for_each_xml_child_node(node, root)
- {
- if (xmlStrEqual(node->name, BAD_CAST "styles"))
- {
- loadHairStylesNode(root);
- }
- else if (xmlStrEqual(node->name, BAD_CAST "colors"))
- {
- loadHairColorsNode(node);
- }
- }
- }
+ if (mHairColors.find(id) != mHairColors.end())
+ logger->log("HairDb: Redefinition of color Id %d in %s", id, filename.c_str());
- delete doc;
+ mHairColors[id] = XML::getProperty(node, "value", COLOR_WHITE);
+}
+void HairDB::checkStatus()
+{
mLoaded = true;
}
@@ -91,27 +65,6 @@ void HairDB::unload()
mLoaded = false;
}
-void HairDB::loadHairColorsNode(xmlNodePtr colorsNode)
-{
- for_each_xml_child_node(node, colorsNode)
- {
- if (xmlStrEqual(node->name, BAD_CAST "color"))
- {
- int id = XML::getProperty(node, "id", 0);
-
- if (mHairColors.find(id) != mHairColors.end())
- logger->log("HairDb: Redefinition of color Id %d", id);
-
- mHairColors[id] = XML::getProperty(node, "value", COLOR_WHITE);
- }
- }
-}
-
-void HairDB::loadHairStylesNode(xmlNodePtr stylesNode)
-{
- // TODO: Add support of the races.xml file.
-}
-
void HairDB::addHairStyle(int id)
{
// TODO: Adapt the sprite handling with hair styles separated from items.
@@ -128,8 +81,10 @@ void HairDB::addHairStyle(int id)
const std::string &HairDB::getHairColor(int id)
{
if (!mLoaded)
- load();
-
+ {
+ // no idea if this can happen, but that check existed before
+ logger->log("WARNING: HairDB::getHairColor() called before settings were loaded!");
+ }
ColorConstIterator it = mHairColors.find(id);
if (it != mHairColors.end())
return it->second;
diff --git a/src/resources/hairdb.h b/src/resources/hairdb.h
index 700bd8b7..502d7c21 100644
--- a/src/resources/hairdb.h
+++ b/src/resources/hairdb.h
@@ -1,7 +1,7 @@
/*
* Hair database
* Copyright (C) 2008 Aethyra Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -26,6 +26,7 @@
#include <map>
#include <string>
+#include "utils/xml.h"
/**
* Hair information database.
@@ -40,10 +41,11 @@ class HairDB
~HairDB()
{ unload(); }
- /**
- * Loads the color data from <code>hair.xml</code>.
- */
- void load();
+ void init();
+
+ void readHairColorNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
/**
* Clear the color data
diff --git a/src/resources/monsterdb.cpp b/src/resources/monsterdb.cpp
index 241cc053..8415b6ae 100644
--- a/src/resources/monsterdb.cpp
+++ b/src/resources/monsterdb.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-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -29,131 +29,135 @@
#include "utils/dtor.h"
#include "utils/gettext.h"
-#include "utils/xml.h"
#include "configuration.h"
#define OLD_TMWATHENA_OFFSET 1002
+
namespace
{
BeingInfos mMonsterInfos;
bool mLoaded = false;
+ int mMonsterIdOffset;
}
-void MonsterDB::load()
+
+/**
+ * Initialize MonsterDB
+ *
+ * If it was initialized before, unload() will be called first.
+ */
+void MonsterDB::init()
{
if (mLoaded)
unload();
- logger->log("Initializing monster database...");
+ // This used to be read from offset attribute of monsters root tag, however
+ // I couldn't find any place it was used, so for now the default values are set
+ mMonsterIdOffset = Net::getNetworkType() == ServerInfo::TMWATHENA ? OLD_TMWATHENA_OFFSET : 0;
+}
- XML::Document doc("monsters.xml");
- xmlNodePtr rootNode = doc.rootNode();
+/**
+ * Read <monster> node from settings.
+ */
+void MonsterDB::readMonsterNode(xmlNodePtr node, const std::string &filename)
+{
+ BeingInfo *currentInfo = new BeingInfo;
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "monsters"))
- {
- logger->error("Monster Database: Error while loading monster.xml!");
- }
+ currentInfo->setWalkMask(Map::BLOCKMASK_WALL
+ | Map::BLOCKMASK_CHARACTER
+ | Map::BLOCKMASK_MONSTER);
+ currentInfo->setBlockType(Map::BLOCKTYPE_MONSTER);
+
+ currentInfo->setName(XML::getProperty(node, "name", _("unnamed")));
- int offset = XML::getProperty(rootNode, "offset", Net::getNetworkType() ==
- ServerInfo::TMWATHENA ? OLD_TMWATHENA_OFFSET : 0);
+ currentInfo->setTargetCursorSize(XML::getProperty(node,
+ "targetCursor", "medium"));
- //iterate <monster>s
- for_each_xml_child_node(monsterNode, rootNode)
+ SpriteDisplay display;
+
+ //iterate <sprite>s and <sound>s
+ for_each_xml_child_node(spriteNode, node)
{
- if (!xmlStrEqual(monsterNode->name, BAD_CAST "monster"))
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
- continue;
+ SpriteReference currentSprite;
+ currentSprite.sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite.variant = XML::getProperty(spriteNode, "variant", 0);
+ display.sprites.push_back(currentSprite);
}
-
- BeingInfo *currentInfo = new BeingInfo;
-
- currentInfo->setWalkMask(Map::BLOCKMASK_WALL
- | Map::BLOCKMASK_CHARACTER
- | Map::BLOCKMASK_MONSTER);
- currentInfo->setBlockType(Map::BLOCKTYPE_MONSTER);
-
- currentInfo->setName(XML::getProperty(monsterNode, "name", _("unnamed")));
-
- currentInfo->setTargetCursorSize(XML::getProperty(monsterNode,
- "targetCursor", "medium"));
-
- SpriteDisplay display;
-
- //iterate <sprite>s and <sound>s
- for_each_xml_child_node(spriteNode, monsterNode)
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
{
- if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
+ std::string event = XML::getProperty(spriteNode, "event", "");
+ const char *soundFile;
+ soundFile = (const char*) spriteNode->xmlChildrenNode->content;
+
+ if (event == "hit")
+ {
+ currentInfo->addSound(SOUND_EVENT_HIT, soundFile);
+ }
+ else if (event == "miss")
{
- SpriteReference currentSprite;
- currentSprite.sprite = (const char*)spriteNode->xmlChildrenNode->content;
- currentSprite.variant = XML::getProperty(spriteNode, "variant", 0);
- display.sprites.push_back(currentSprite);
+ currentInfo->addSound(SOUND_EVENT_MISS, soundFile);
}
- else if (xmlStrEqual(spriteNode->name, BAD_CAST "sound"))
+ else if (event == "hurt")
{
- std::string event = XML::getProperty(spriteNode, "event", "");
- const char *filename;
- filename = (const char*) spriteNode->xmlChildrenNode->content;
-
- if (event == "hit")
- {
- currentInfo->addSound(SOUND_EVENT_HIT, filename);
- }
- else if (event == "miss")
- {
- currentInfo->addSound(SOUND_EVENT_MISS, filename);
- }
- else if (event == "hurt")
- {
- currentInfo->addSound(SOUND_EVENT_HURT, filename);
- }
- else if (event == "die")
- {
- currentInfo->addSound(SOUND_EVENT_DIE, filename);
- }
- else
- {
- logger->log("MonsterDB: Warning, sound effect %s for "
- "unknown event %s of monster %s",
- filename, event.c_str(),
- currentInfo->getName().c_str());
- }
+ currentInfo->addSound(SOUND_EVENT_HURT, soundFile);
}
- else if (xmlStrEqual(spriteNode->name, BAD_CAST "attack"))
+ else if (event == "die")
{
- const int id = XML::getProperty(spriteNode, "id", 0);
- int effectId = XML::getProperty(spriteNode, "effect-id", -1);
- int hitEffectId =
- XML::getProperty(spriteNode, "hit-effect-id",
- paths.getIntValue("hitEffectId"));
- int criticalHitEffectId =
- XML::getProperty(spriteNode, "critical-hit-effect-id",
- paths.getIntValue("criticalHitEffectId"));
- const std::string missileParticleFilename =
- XML::getProperty(spriteNode, "missile-particle", "");
-
- const std::string spriteAction = XML::getProperty(spriteNode,
- "action",
- "attack");
-
- currentInfo->addAttack(id, spriteAction, effectId,
- hitEffectId, criticalHitEffectId,
- missileParticleFilename);
+ currentInfo->addSound(SOUND_EVENT_DIE, soundFile);
}
- else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ else
{
- display.particles.push_back(
- (const char*) spriteNode->xmlChildrenNode->content);
+ logger->log("MonsterDB: Warning, sound effect %s for "
+ "unknown event %s of monster %s in %s",
+ soundFile, event.c_str(),
+ currentInfo->getName().c_str(),
+ filename.c_str());
}
}
- currentInfo->setDisplay(display);
-
- mMonsterInfos[XML::getProperty(monsterNode, "id", 0) + offset] = currentInfo;
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "attack"))
+ {
+ const int id = XML::getProperty(spriteNode, "id", 0);
+ int effectId = XML::getProperty(spriteNode, "effect-id", -1);
+ int hitEffectId =
+ XML::getProperty(spriteNode, "hit-effect-id",
+ paths.getIntValue("hitEffectId"));
+ int criticalHitEffectId =
+ XML::getProperty(spriteNode, "critical-hit-effect-id",
+ paths.getIntValue("criticalHitEffectId"));
+ const std::string missileParticleFilename =
+ XML::getProperty(spriteNode, "missile-particle", "");
+
+ const std::string spriteAction = XML::getProperty(spriteNode,
+ "action",
+ "attack");
+
+ currentInfo->addAttack(id, spriteAction, effectId,
+ hitEffectId, criticalHitEffectId,
+ missileParticleFilename);
+ }
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
+ {
+ display.particles.push_back(
+ (const char*) spriteNode->xmlChildrenNode->content);
+ }
}
+ currentInfo->setDisplay(display);
+
+ mMonsterInfos[XML::getProperty(node, "id", 0) + mMonsterIdOffset] = currentInfo;
- mLoaded = true;
+
+}
+
+/**
+ * Check if everything was loaded correctly
+ */
+void MonsterDB::checkStatus()
+{
+ // there is nothing to check for now
}
void MonsterDB::unload()
diff --git a/src/resources/monsterdb.h b/src/resources/monsterdb.h
index 8ea3afdf..5b2f3c2d 100644
--- a/src/resources/monsterdb.h
+++ b/src/resources/monsterdb.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-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -22,6 +22,8 @@
#ifndef MONSTER_DB_H
#define MONSTER_DB_H
+#include "utils/xml.h"
+
class BeingInfo;
/**
@@ -29,7 +31,11 @@ class BeingInfo;
*/
namespace MonsterDB
{
- void load();
+ void init();
+
+ void readMonsterNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
void unload();
diff --git a/src/resources/npcdb.cpp b/src/resources/npcdb.cpp
index 45b36dfe..7d0f72b0 100644
--- a/src/resources/npcdb.cpp
+++ b/src/resources/npcdb.cpp
@@ -1,7 +1,7 @@
/*
* The Mana Client
* Copyright (C) 2008-2009 The Mana World Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -35,61 +35,52 @@ namespace
bool mLoaded = false;
}
-void NPCDB::load()
+
+void NPCDB::init()
{
if (mLoaded)
unload();
- logger->log("Initializing NPC database...");
-
- XML::Document doc("npcs.xml");
- xmlNodePtr rootNode = doc.rootNode();
+}
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "npcs"))
+void NPCDB::readNPCNode(xmlNodePtr node, const std::string &filename)
+{
+ int id = XML::getProperty(node, "id", 0);
+ if (id == 0)
{
- logger->error("NPC Database: Error while loading npcs.xml!");
+ logger->log("NPC Database: NPC with missing ID in %s", filename.c_str());
+ return;
}
- //iterate <npc>s
- for_each_xml_child_node(npcNode, rootNode)
- {
- if (!xmlStrEqual(npcNode->name, BAD_CAST "npc"))
- continue;
+ BeingInfo *currentInfo = new BeingInfo;
+
+ currentInfo->setTargetCursorSize(XML::getProperty(node,
+ "targetCursor", "medium"));
- int id = XML::getProperty(npcNode, "id", 0);
- if (id == 0)
+ SpriteDisplay display;
+ for_each_xml_child_node(spriteNode, node)
+ {
+ if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
{
- logger->log("NPC Database: NPC with missing ID in npcs.xml!");
- continue;
+ SpriteReference currentSprite;
+ currentSprite.sprite = (const char*)spriteNode->xmlChildrenNode->content;
+ currentSprite.variant = XML::getProperty(spriteNode, "variant", 0);
+ display.sprites.push_back(currentSprite);
}
-
- BeingInfo *currentInfo = new BeingInfo;
-
- currentInfo->setTargetCursorSize(XML::getProperty(npcNode,
- "targetCursor", "medium"));
-
- SpriteDisplay display;
- for_each_xml_child_node(spriteNode, npcNode)
+ else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
{
- if (xmlStrEqual(spriteNode->name, BAD_CAST "sprite"))
- {
- SpriteReference currentSprite;
- currentSprite.sprite = (const char*)spriteNode->xmlChildrenNode->content;
- currentSprite.variant = XML::getProperty(spriteNode, "variant", 0);
- display.sprites.push_back(currentSprite);
- }
- else if (xmlStrEqual(spriteNode->name, BAD_CAST "particlefx"))
- {
- std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
- display.particles.push_back(particlefx);
- }
+ std::string particlefx = (const char*)spriteNode->xmlChildrenNode->content;
+ display.particles.push_back(particlefx);
}
+ }
- currentInfo->setDisplay(display);
+ currentInfo->setDisplay(display);
- mNPCInfos[id] = currentInfo;
- }
+ mNPCInfos[id] = currentInfo;
+}
+void NPCDB::checkStatus()
+{
mLoaded = true;
}
diff --git a/src/resources/npcdb.h b/src/resources/npcdb.h
index 16af7a5f..a3718a7b 100644
--- a/src/resources/npcdb.h
+++ b/src/resources/npcdb.h
@@ -1,7 +1,7 @@
/*
* The Mana Client
* Copyright (C) 2008-2009 The Mana World Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -22,6 +22,9 @@
#ifndef NPC_DB_H
#define NPC_DB_H
+#include <string>
+#include "utils/xml.h"
+
class BeingInfo;
/**
@@ -29,7 +32,11 @@ class BeingInfo;
*/
namespace NPCDB
{
- void load();
+ void init();
+
+ void readNPCNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
void unload();
diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp
new file mode 100644
index 00000000..3cbb115c
--- /dev/null
+++ b/src/resources/settingsmanager.cpp
@@ -0,0 +1,191 @@
+/*
+ * The Mana Server
+ * Copyright (C) 2013 The Mana World Development Team
+ *
+ * This file is part of The Mana Server.
+ *
+ * The Mana Server is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "resources/settingsmanager.h"
+
+#include "resources/attributes.h"
+#include "resources/monsterdb.h"
+#include "resources/hairdb.h"
+#include "resources/specialdb.h"
+#include "resources/npcdb.h"
+#include "resources/emotedb.h"
+#include "statuseffect.h"
+#include "units.h"
+
+#include "net/manaserv/itemhandler.h"
+#include "net/net.h"
+
+#include "utils/xml.h"
+#include "utils/path.h"
+#include "log.h"
+
+namespace SettingsManager
+{
+ std::string mSettingsFile;
+ std::set<std::string> mIncludedFiles;
+
+ static void loadFile(const std::string &filename);
+
+ void load()
+ {
+ // initialize managers
+ Attributes::init();
+ hairDB.init();
+ MonsterDB::init();
+ SpecialDB::init();
+ NPCDB::init();
+ EmoteDB::init();
+ StatusEffect::init();
+ Units::init();
+
+ // load stuff from settings
+ loadFile("settings.xml");
+
+ Attributes::checkStatus();
+ hairDB.checkStatus();
+ MonsterDB::checkStatus();
+ SpecialDB::checkStatus();
+ NPCDB::checkStatus();
+ EmoteDB::checkStatus();
+ StatusEffect::checkStatus();
+ Units::checkStatus();
+
+ if (Net::getNetworkType() == ServerInfo::MANASERV)
+ {
+ Attributes::informItemDB();
+ }
+ }
+
+ void unload()
+ {
+ StatusEffect::unload();
+ EmoteDB::unload();
+ NPCDB::unload();
+ SpecialDB::unload();
+ MonsterDB::unload();
+ hairDB.unload();
+ Attributes::unload();
+ }
+
+ /**
+ * Loads a settings file.
+ */
+ static void loadFile(const std::string &filename)
+ {
+ logger->log("Loading game settings from %s", filename.c_str());
+
+ XML::Document doc(filename);
+ xmlNodePtr node = doc.rootNode();
+
+ // add file to include set
+ mIncludedFiles.insert(filename);
+
+ // FIXME: check root node's name when bjorn decides it's time
+ if (!node /*|| !xmlStrEqual(node->name, BAD_CAST "settings") */)
+ {
+ logger->log("Settings Manager: %s is not a valid settings file!", filename.c_str());
+ return;
+ }
+
+
+ // go through every node
+ for_each_xml_child_node(childNode, node)
+ {
+ if (childNode->type != XML_ELEMENT_NODE)
+ continue;
+
+ if (xmlStrEqual(childNode->name, BAD_CAST "include"))
+ {
+ // include an other file
+ const std::string includeFile = XML::getProperty(childNode, "file", std::string());
+
+ // check if file property was given
+ if (!includeFile.empty())
+ {
+ // build absolute path path
+ const utils::splittedPath splittedPath = utils::splitFileNameAndPath(filename);
+ const std::string realIncludeFile = utils::cleanPath(
+ utils::joinPaths(splittedPath.path, includeFile));
+
+ // check if we're not entering a loop
+ if (mIncludedFiles.find(realIncludeFile) != mIncludedFiles.end())
+ {
+ logger->log("Circular include loop detecting while including %s from %s", includeFile.c_str(), filename.c_str());
+ }
+ else
+ {
+ // include that file
+ loadFile(realIncludeFile);
+ }
+ }
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "attribute"))
+ {
+ // map config
+ Attributes::readAttributeNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "points"))
+ {
+ Attributes::readPointsNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "color"))
+ {
+ hairDB.readHairColorNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "monster"))
+ {
+ MonsterDB::readMonsterNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "special-set"))
+ {
+ SpecialDB::readSpecialSetNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "npc"))
+ {
+ NPCDB::readNPCNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "emote"))
+ {
+ EmoteDB::readEmoteNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "status-effect") || xmlStrEqual(childNode->name, BAD_CAST "stun-effect"))
+ {
+ StatusEffect::readStatusEffectNode(childNode, filename);
+ }
+ else if (xmlStrEqual(childNode->name, BAD_CAST "unit"))
+ {
+ Units::readUnitNode(childNode, filename);
+ }
+ else
+ {
+ // compatibility stuff with older configs/games
+ if (xmlStrEqual(node->name, BAD_CAST "specials") && xmlStrEqual(childNode->name, BAD_CAST "set"))
+ {
+ // specials.xml:/specials/set
+ SpecialDB::readSpecialSetNode(childNode, filename);
+ }
+ }
+ }
+
+ mIncludedFiles.erase(filename);
+ }
+
+}
+
diff --git a/src/resources/settingsmanager.h b/src/resources/settingsmanager.h
new file mode 100644
index 00000000..25feb86b
--- /dev/null
+++ b/src/resources/settingsmanager.h
@@ -0,0 +1,35 @@
+/*
+ * The Mana Client
+ * Copyright (C) 2013 The Mana Developers
+ *
+ * This file is part of The Mana Client.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef SETTINGSMANAGER_HPP
+#define SETTINGSMANAGER_HPP
+
+#include <string>
+#include <list>
+#include <set>
+
+namespace SettingsManager
+{
+ void load();
+ void unload();
+}
+
+
+#endif // SETTINGSMANAGER_HPP
diff --git a/src/resources/specialdb.cpp b/src/resources/specialdb.cpp
index c75f4b1b..6601b586 100644
--- a/src/resources/specialdb.cpp
+++ b/src/resources/specialdb.cpp
@@ -1,6 +1,6 @@
/*
* The Mana Client
- * Copyright (C) 2010-2012 The Mana Developers
+ * Copyright (C) 2010-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -23,7 +23,6 @@
#include "log.h"
#include "utils/dtor.h"
-#include "utils/xml.h"
namespace
@@ -41,63 +40,51 @@ SpecialInfo::TargetMode SpecialDB::targetModeFromString(const std::string& str)
return SpecialInfo::TARGET_BEING;
}
-void SpecialDB::load()
+
+void SpecialDB::init()
{
if (mLoaded)
unload();
+}
- logger->log("Initializing special database...");
-
- XML::Document doc("specials.xml");
- xmlNodePtr root = doc.rootNode();
-
- if (!root || !xmlStrEqual(root->name, BAD_CAST "specials"))
- {
- logger->log("Error loading specials file specials.xml");
- return;
- }
-
- std::string setName;
+void SpecialDB::readSpecialSetNode(xmlNodePtr node, const std::string &filename)
+{
+ std::string setName = XML::getProperty(node, "name", "Actions");
- for_each_xml_child_node(set, root)
+ for_each_xml_child_node(special, node)
{
- if (xmlStrEqual(set->name, BAD_CAST "set") ||
- xmlStrEqual(set->name, BAD_CAST "special-set"))
+ if (xmlStrEqual(special->name, BAD_CAST "special"))
{
- setName = XML::getProperty(set, "name", "Actions");
+ SpecialInfo *info = new SpecialInfo();
+ int id = XML::getProperty(special, "id", 0);
+ info->id = id;
+ info->set = setName;
+ info->name = XML::getProperty(special, "name", "");
+ info->icon = XML::getProperty(special, "icon", "");
+
+ info->targetMode = targetModeFromString(XML::getProperty(special, "target", "being"));
+ info->rechargeable = XML::getBoolProperty(special, "rechargeable", true);
+ info->rechargeNeeded = 0;
+ info->rechargeCurrent = 0;
- for_each_xml_child_node(special, set)
+ if (mSpecialInfos.find(id) != mSpecialInfos.end())
{
- if (xmlStrEqual(special->name, BAD_CAST "special"))
- {
- SpecialInfo *info = new SpecialInfo();
- int id = XML::getProperty(special, "id", 0);
- info->id = id;
- info->set = setName;
- info->name = XML::getProperty(special, "name", "");
- info->icon = XML::getProperty(special, "icon", "");
-
- info->targetMode = targetModeFromString(XML::getProperty(special, "target", "being"));
-
- info->rechargeable = XML::getBoolProperty(special, "rechargeable", true);
- info->rechargeNeeded = 0;
- info->rechargeCurrent = 0;
-
- if (mSpecialInfos.find(id) != mSpecialInfos.end())
- {
- logger->log("SpecialDB: Duplicate special ID %d (ignoring)", id);
- } else {
- mSpecialInfos[id] = info;
- }
- }
+ logger->log("SpecialDB: Duplicate special ID %d in %s, ignoring", id, filename.c_str());
+ } else {
+ mSpecialInfos[id] = info;
}
}
}
+}
+
+void SpecialDB::checkStatus()
+{
mLoaded = true;
}
+
void SpecialDB::unload()
{
diff --git a/src/resources/specialdb.h b/src/resources/specialdb.h
index dc1c26b6..f6987b71 100644
--- a/src/resources/specialdb.h
+++ b/src/resources/specialdb.h
@@ -1,6 +1,6 @@
/*
* The Mana Client
- * Copyright (C) 2010-2012 The Mana Developers
+ * Copyright (C) 2010-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -23,6 +23,7 @@
#include <string>
#include <map>
+#include "utils/xml.h"
struct SpecialInfo
{
@@ -48,7 +49,11 @@ struct SpecialInfo
*/
namespace SpecialDB
{
- void load();
+ void init();
+
+ void readSpecialSetNode(xmlNodePtr node, const std::string &filename);
+
+ void checkStatus();
void unload();
diff --git a/src/statuseffect.cpp b/src/statuseffect.cpp
index 659aeaf3..bdaaf566 100644
--- a/src/statuseffect.cpp
+++ b/src/statuseffect.cpp
@@ -1,7 +1,7 @@
/*
* The Mana Client
* Copyright (C) 2008-2009 The Mana World Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -25,8 +25,6 @@
#include "log.h"
#include "sound.h"
-#include "utils/xml.h"
-
#include "configuration.h"
#include <map>
@@ -114,58 +112,52 @@ StatusEffect *StatusEffect::getStunEffect(int index, bool enabling)
return stunEffects[enabling][index];
}
-void StatusEffect::load()
+void StatusEffect::init()
{
if (mLoaded)
unload();
+}
- XML::Document doc(STATUS_EFFECTS_FILE);
- xmlNodePtr rootNode = doc.rootNode();
-
- if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "status-effects"))
+void StatusEffect::readStatusEffectNode(xmlNodePtr node, const std::string &filename)
+{
+ status_effect_map *the_map = NULL;
+ int index = atoi(XML::getProperty(node, "id", "-1").c_str());
+ if (xmlStrEqual(node->name, BAD_CAST "status-effect"))
{
- logger->log("Error loading status effects file: " STATUS_EFFECTS_FILE);
- return;
+ the_map = &statusEffects;
+ int block_index = atoi(XML::getProperty(node, "block-id", "-1").c_str());
+
+ if (index >= 0 && block_index >= 0)
+ blockEffectIndexMap[block_index] = index;
}
+ else if (xmlStrEqual(node->name, BAD_CAST "stun-effect"))
+ the_map = &stunEffects;
- for_each_xml_child_node(node, rootNode)
+ if (the_map)
{
- status_effect_map *the_map = NULL;
-
- int index = atoi(XML::getProperty(node, "id", "-1").c_str());
-
- if (xmlStrEqual(node->name, BAD_CAST "status-effect"))
- {
- the_map = &statusEffects;
- int block_index = atoi(XML::getProperty(node, "block-id", "-1").c_str());
-
- if (index >= 0 && block_index >= 0)
- blockEffectIndexMap[block_index] = index;
+ StatusEffect *startEffect = new StatusEffect;
+ StatusEffect *endEffect = new StatusEffect;
+
+ startEffect->mMessage = XML::getProperty(node, "start-message", "");
+ startEffect->mSFXEffect = XML::getProperty(node, "start-audio", "");
+ startEffect->mParticleEffect = XML::getProperty(node, "start-particle", "");
+ startEffect->mIcon = XML::getProperty(node, "icon", "");
+ startEffect->mAction = XML::getProperty(node, "action", "");
+ startEffect->mPersistentParticleEffect = (XML::getProperty(node, "persistent-particle-effect", "no")) != "no";
+
+ endEffect->mMessage = XML::getProperty(node, "end-message", "");
+ endEffect->mSFXEffect = XML::getProperty(node, "end-audio", "");
+ endEffect->mParticleEffect = XML::getProperty(node, "end-particle", "");
+
+ (*the_map)[1][index] = startEffect;
+ (*the_map)[0][index] = endEffect;
+ }
- }
- else if (xmlStrEqual(node->name, BAD_CAST "stun-effect"))
- the_map = &stunEffects;
+}
- if (the_map)
- {
- StatusEffect *startEffect = new StatusEffect;
- StatusEffect *endEffect = new StatusEffect;
-
- startEffect->mMessage = XML::getProperty(node, "start-message", "");
- startEffect->mSFXEffect = XML::getProperty(node, "start-audio", "");
- startEffect->mParticleEffect = XML::getProperty(node, "start-particle", "");
- startEffect->mIcon = XML::getProperty(node, "icon", "");
- startEffect->mAction = XML::getProperty(node, "action", "");
- startEffect->mPersistentParticleEffect = (XML::getProperty(node, "persistent-particle-effect", "no")) != "no";
-
- endEffect->mMessage = XML::getProperty(node, "end-message", "");
- endEffect->mSFXEffect = XML::getProperty(node, "end-audio", "");
- endEffect->mParticleEffect = XML::getProperty(node, "end-particle", "");
-
- (*the_map)[1][index] = startEffect;
- (*the_map)[0][index] = endEffect;
- }
- }
+void StatusEffect::checkStatus()
+{
+ mLoaded = true;
}
void unloadMap(std::map<int, StatusEffect *> map)
diff --git a/src/statuseffect.h b/src/statuseffect.h
index 432f1c0e..5b1a7e23 100644
--- a/src/statuseffect.h
+++ b/src/statuseffect.h
@@ -1,7 +1,7 @@
/*
* The Mana Client
* Copyright (C) 2008-2009 The Mana World Development Team
- * Copyright (C) 2009-2012 The Mana Developers
+ * Copyright (C) 2009-2013 The Mana Developers
*
* This file is part of The Mana Client.
*
@@ -26,6 +26,7 @@
#include "animatedsprite.h"
#include "resources/animation.h"
+#include "utils/xml.h"
class StatusEffect
{
@@ -94,7 +95,11 @@ public:
*/
static int blockEffectIndexToEffectIndex(int blocKIndex);
- static void load();
+ static void init();
+
+ static void readStatusEffectNode(xmlNodePtr node, const std::string &filename);
+
+ static void checkStatus();
static void unload();
private:
diff --git a/src/units.cpp b/src/units.cpp
index 59181bde..1487eb21 100644
--- a/src/units.cpp
+++ b/src/units.cpp
@@ -50,7 +50,8 @@ enum UnitType {
struct UnitDescription units[UNIT_END];
-void Units::loadUnits()
+
+void Units::init()
{
{ // Setup default weight
struct UnitDescription ud;
@@ -90,72 +91,66 @@ void Units::loadUnits()
units[UNIT_CURRENCY] = ud;
}
+}
- XML::Document doc("units.xml");
- xmlNodePtr root = doc.rootNode();
+void Units::readUnitNode(xmlNodePtr node, const std::string &filename)
+{
+ struct UnitDescription ud;
+ int level = 1;
+ const std::string type = XML::getProperty(node, "type", "");
+ ud.conversion = XML::getProperty(node, "conversion", 1);
+ ud.mix = XML::getProperty(node, "mix", "no") == "yes";
- if (!root || !xmlStrEqual(root->name, BAD_CAST "units"))
- {
- logger->log("Error loading unit definition file: units.xml");
- return;
- }
+ struct UnitLevel bu;
+ bu.symbol = XML::getProperty(node, "base", "¤");
+ bu.count = 1;
+ bu.round = XML::getProperty(node, "round", 2);
+
+ ud.levels.push_back(bu);
- for_each_xml_child_node(node, root)
+ for_each_xml_child_node(uLevel, node)
{
- if (xmlStrEqual(node->name, BAD_CAST "unit"))
+ if (xmlStrEqual(uLevel->name, BAD_CAST "level"))
{
- struct UnitDescription ud;
- int level = 1;
- const std::string type = XML::getProperty(node, "type", "");
- ud.conversion = XML::getProperty(node, "conversion", 1);
- ud.mix = XML::getProperty(node, "mix", "no") == "yes";
-
- struct UnitLevel bu;
- bu.symbol = XML::getProperty(node, "base", "¤");
- bu.count = 1;
- bu.round = XML::getProperty(node, "round", 2);
+ struct UnitLevel ul;
+ ul.symbol = XML::getProperty(uLevel, "symbol",
+ strprintf("¤%d",level));
+ ul.count = XML::getProperty(uLevel, "count", -1);
+ ul.round = XML::getProperty(uLevel, "round", bu.round);
- ud.levels.push_back(bu);
-
- for_each_xml_child_node(uLevel, node)
+ if (ul.count > 0)
{
- if (xmlStrEqual(uLevel->name, BAD_CAST "level"))
- {
- struct UnitLevel ul;
- ul.symbol = XML::getProperty(uLevel, "symbol",
- strprintf("¤%d",level));
- ul.count = XML::getProperty(uLevel, "count", -1);
- ul.round = XML::getProperty(uLevel, "round", bu.round);
-
- if (ul.count > 0)
- {
- ud.levels.push_back(ul);
- level++;
- }
- else
- {
- logger->log("Error bad unit count: %d for %s in %s",
- ul.count, ul.symbol.c_str(), bu.symbol.c_str());
- }
- }
+ ud.levels.push_back(ul);
+ level++;
}
-
- // Add one more level for saftey
- struct UnitLevel ll;
- ll.symbol = "";
- ll.count = INT_MAX;
- ll.round = 0;
-
- ud.levels.push_back(ll);
-
- if (type == "weight")
- units[UNIT_WEIGHT] = ud;
- else if (type == "currency")
- units[UNIT_CURRENCY] = ud;
else
- logger->log("Error unknown unit type: %s", type.c_str());
+ {
+ logger->log("Error bad unit count: %d for %s in %s",
+ ul.count, ul.symbol.c_str(), bu.symbol.c_str());
+ }
}
}
+
+ // Add one more level for saftey
+ struct UnitLevel ll;
+ ll.symbol = "";
+ ll.count = INT_MAX;
+ ll.round = 0;
+
+ ud.levels.push_back(ll);
+
+ if (type == "weight")
+ units[UNIT_WEIGHT] = ud;
+ else if (type == "currency")
+ units[UNIT_CURRENCY] = ud;
+ else
+ logger->log("Error unknown unit type: %s in %s", type.c_str(), filename.c_str());
+
+}
+
+void Units::checkStatus()
+{
+
}
std::string formatUnit(int value, int type)
diff --git a/src/units.h b/src/units.h
index 1e923f33..96953b30 100644
--- a/src/units.h
+++ b/src/units.h
@@ -23,14 +23,16 @@
#define UNITS_H
#include <string>
+#include "utils/xml.h"
class Units
{
public:
- /**
- * Loads and parses the units.xml file (if found).
- */
- static void loadUnits();
+ static void init();
+
+ static void readUnitNode(xmlNodePtr node, const std::string &filename);
+
+ static void checkStatus();
/**
* Formats the given number in the correct currency format.
diff --git a/src/utils/path.cpp b/src/utils/path.cpp
new file mode 100644
index 00000000..95db40d3
--- /dev/null
+++ b/src/utils/path.cpp
@@ -0,0 +1,153 @@
+/*
+ * The Mana Server
+ * Copyright (C) 2013 The Mana World Development Team
+ *
+ * This file is part of The Mana Server.
+ *
+ * The Mana Server is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "utils/path.h"
+#include <vector>
+
+namespace utils
+{
+
+ /**
+ * Returns the filePath sub-part corresponding to the filename only.
+ * @return splittedPath: the file path ending with '/' or '\'
+ * and the file name alone.
+ */
+ splittedPath splitFileNameAndPath(const std::string &fullFilePath)
+ {
+ // We'll reversed-search for '/' or'\' and extract the substrings
+ // corresponding to the filename and the path separately.
+ size_t slashPos = fullFilePath.find_last_of("/\\");
+
+ splittedPath splittedFilePath;
+ // Note the last slash is kept in the path name.
+ splittedFilePath.path = fullFilePath.substr(0, slashPos + 1);
+ splittedFilePath.file = fullFilePath.substr(slashPos + 1);
+
+ return splittedFilePath;
+ }
+
+ /**
+ * Join two path elements into one.
+ *
+ * This function helps build relative paths.
+ *
+ * Examples:
+ *
+ * /foo + bar = /foo/bar
+ * /foo/ + bar = /foo/bar
+ * /foo + /bar = /bar
+ *
+ * This will work for PhysFS paths. Windows style paths (prefixed with drive letters) won't work.
+ *
+ * @return Joined paths or path2 if path2 was an absolute path.
+ */
+ std::string joinPaths(const std::string &path1, const std::string &path2)
+ {
+ if (path2.empty())
+ return path1;
+
+ if (path1.empty())
+ return path2;
+
+ // check if path2 is an absolute path that cannot be joined
+ if (path2[0] == '/' || path2[0] == '\\')
+ return path2;
+
+ char p1end = path1[path1.size()-1];
+ if (p1end == '/' || p1end == '\\')
+ {
+ return path1 + path2;
+ }
+ else
+ {
+ return path1 + "/" + path2;
+ }
+ }
+
+ /**
+ * Removes relative elements from the path.
+ */
+ std::string cleanPath(const std::string &path)
+ {
+ size_t prev, cur;
+ std::string part, result;
+ std::vector<std::string> pathStack;
+
+ prev = 0;
+ while (true)
+ {
+ cur = path.find_first_of("/\\", prev);
+ if (cur == std::string::npos)
+ {
+ // FIXME add everything from prev to the end
+ pathStack.push_back(path.substr(prev));
+ break;
+ }
+
+ part = path.substr(prev, cur - prev);
+ if (part == "..")
+ {
+ // go back one level
+ if (!pathStack.empty())
+ {
+ pathStack.pop_back();
+ }
+ }
+ else if (part == ".")
+ {
+ // do nothing
+ }
+ else if (part == "")
+ {
+ if (pathStack.empty() && cur == 0)
+ {
+ // handle first empty match before the root slash
+ pathStack.push_back(std::string());
+ }
+ else
+ {
+ // empty match in the middle of the path should be ignored
+ }
+ }
+ else
+ {
+ // normal path element
+ pathStack.push_back(part);
+ }
+
+ cur++;
+ prev = cur;
+ }
+
+ // join the pathStack into a normal path
+ unsigned int i = 0;
+ for (i = 0; i < pathStack.size(); i++)
+ {
+ result += pathStack[i];
+ if (i < pathStack.size() - 1) {
+ result += "/";
+ }
+ }
+
+ return result;
+ }
+
+
+}
diff --git a/src/utils/path.h b/src/utils/path.h
new file mode 100644
index 00000000..2ad9e987
--- /dev/null
+++ b/src/utils/path.h
@@ -0,0 +1,42 @@
+/*
+ * The Mana Server
+ * Copyright (C) 2013 The Mana World Development Team
+ *
+ * This file is part of The Mana Server.
+ *
+ * The Mana Server is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * any later version.
+ *
+ * The Mana Server is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with The Mana Server. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef UTILS_PATH_H
+#define UTILS_PATH_H
+
+#include <string>
+
+namespace utils
+{
+
+ struct splittedPath
+ {
+ std::string path;
+ std::string file;
+ };
+
+ splittedPath splitFileNameAndPath(const std::string &fullFilePath);
+
+ std::string joinPaths(const std::string &path1, const std::string &path2);
+
+ std::string cleanPath(const std::string &path);
+
+}
+#endif // UTILS_PATH_H