From 7fa9db23c67c690f8d96d5bd1ea2d0c39f52a0ac Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Thu, 2 May 2013 22:10:21 +0200 Subject: Fixed network layer doing delayed actor deletion The delayed actor deletion was meant to be used during the logic calls, to avoid modifying the container while it is being iterated. The deletions happening from the network layer are not done while iterating the set of actors, so it can delete immediately. This fixes an issue where an NPC would disappear when changing appearance on tmwAthena, because this was implemented as a remove + add, which broke due to the delayed deletion. Mantis-issue: 507 Reviewed-by: Jared Adams --- src/actorspritemanager.cpp | 9 ++++++++- src/actorspritemanager.h | 7 ++++++- src/being.cpp | 2 +- src/net/manaserv/beinghandler.cpp | 2 +- src/net/manaserv/itemhandler.cpp | 2 +- src/net/tmwa/beinghandler.cpp | 2 +- src/net/tmwa/itemhandler.cpp | 2 +- 7 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/actorspritemanager.cpp b/src/actorspritemanager.cpp index 31b6d8f0..7da9fe10 100644 --- a/src/actorspritemanager.cpp +++ b/src/actorspritemanager.cpp @@ -138,7 +138,14 @@ FloorItem *ActorSpriteManager::createItem(int id, int itemId, const Vector &pos) return floorItem; } -void ActorSpriteManager::destroy(ActorSprite *actor) +void ActorSpriteManager::destroyActor(ActorSprite *actor) +{ + mActors.erase(actor); + mDeleteActors.erase(actor); + delete actor; +} + +void ActorSpriteManager::scheduleDelete(ActorSprite *actor) { if (!actor || actor == local_player) return; diff --git a/src/actorspritemanager.h b/src/actorspritemanager.h index 8ff9ff39..76364ea5 100644 --- a/src/actorspritemanager.h +++ b/src/actorspritemanager.h @@ -66,11 +66,16 @@ class ActorSpriteManager */ FloorItem *createItem(int id, int itemId, const Vector &position); + /** + * Immediately destroys the given \a actor. + */ + void destroyActor(ActorSprite *actor); + /** * Destroys the given ActorSprite at the end of * ActorSpriteManager::logic. */ - void destroy(ActorSprite *actor); + void scheduleDelete(ActorSprite *actor); /** * Returns a specific Being, by id; diff --git a/src/being.cpp b/src/being.cpp index 62081bb4..21d48ed2 100644 --- a/src/being.cpp +++ b/src/being.cpp @@ -892,7 +892,7 @@ void Being::logic() { if (getType() != PLAYER) - actorSpriteManager->destroy(this); + actorSpriteManager->scheduleDelete(this); } } diff --git a/src/net/manaserv/beinghandler.cpp b/src/net/manaserv/beinghandler.cpp index 52f6dab4..61b4ef81 100644 --- a/src/net/manaserv/beinghandler.cpp +++ b/src/net/manaserv/beinghandler.cpp @@ -176,7 +176,7 @@ void BeingHandler::handleBeingLeaveMessage(MessageIn &msg) if (!being) return; - actorSpriteManager->destroy(being); + actorSpriteManager->destroyActor(being); } void BeingHandler::handleBeingsMoveMessage(MessageIn &msg) diff --git a/src/net/manaserv/itemhandler.cpp b/src/net/manaserv/itemhandler.cpp index 4e29bb4f..de5b36fa 100644 --- a/src/net/manaserv/itemhandler.cpp +++ b/src/net/manaserv/itemhandler.cpp @@ -60,7 +60,7 @@ void ItemHandler::handleMessage(MessageIn &msg) } else if (FloorItem *item = actorSpriteManager->findItem(id)) { - actorSpriteManager->destroy(item); + actorSpriteManager->destroyActor(item); } } } break; diff --git a/src/net/tmwa/beinghandler.cpp b/src/net/tmwa/beinghandler.cpp index fb01990a..12c97feb 100644 --- a/src/net/tmwa/beinghandler.cpp +++ b/src/net/tmwa/beinghandler.cpp @@ -327,7 +327,7 @@ void BeingHandler::handleMessage(MessageIn &msg) if (msg.readInt8() == 1) dstBeing->setAction(Being::DEAD); else - actorSpriteManager->destroy(dstBeing); + actorSpriteManager->destroyActor(dstBeing); break; diff --git a/src/net/tmwa/itemhandler.cpp b/src/net/tmwa/itemhandler.cpp index f05bb899..6ad0ad4c 100644 --- a/src/net/tmwa/itemhandler.cpp +++ b/src/net/tmwa/itemhandler.cpp @@ -67,7 +67,7 @@ void ItemHandler::handleMessage(MessageIn &msg) case SMSG_ITEM_REMOVE: if (FloorItem *item = actorSpriteManager->findItem(msg.readInt32())) - actorSpriteManager->destroy(item); + actorSpriteManager->destroyActor(item); break; } } -- cgit v1.2.3-70-g09d2 From 0ef59afb6ee029a4e2247684f3f32f5bd064eb0b Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Sat, 4 May 2013 10:24:44 +0200 Subject: Fixed codeblocks project --- mana.cbp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mana.cbp b/mana.cbp index 956c1ff1..f25a33c4 100644 --- a/mana.cbp +++ b/mana.cbp @@ -394,8 +394,6 @@ - - @@ -522,6 +520,8 @@ + + -- cgit v1.2.3-70-g09d2 From bd1fdd87eed48ba3ffcc413936d6a6a60a429a97 Mon Sep 17 00:00:00 2001 From: Przemysław Grzywacz Date: Sat, 4 May 2013 21:57:58 +0200 Subject: Client-side settings are now available from settings.xml --- AUTHORS | 1 + mana.cbp | 4 + mana.files | 4 + src/CMakeLists.txt | 4 + src/client.cpp | 20 ++-- src/net/manaserv/generalhandler.cpp | 10 -- src/net/tmwa/generalhandler.cpp | 14 +-- src/resources/attributes.cpp | 188 +++++++++++++++++------------------ src/resources/attributes.h | 13 ++- src/resources/emotedb.cpp | 116 ++++++++++------------ src/resources/emotedb.h | 9 +- src/resources/hairdb.cpp | 79 ++++----------- src/resources/hairdb.h | 12 ++- src/resources/monsterdb.cpp | 188 ++++++++++++++++++----------------- src/resources/monsterdb.h | 10 +- src/resources/npcdb.cpp | 71 ++++++-------- src/resources/npcdb.h | 11 ++- src/resources/settingsmanager.cpp | 191 ++++++++++++++++++++++++++++++++++++ src/resources/settingsmanager.h | 35 +++++++ src/resources/specialdb.cpp | 71 ++++++-------- src/resources/specialdb.h | 9 +- src/statuseffect.cpp | 82 +++++++--------- src/statuseffect.h | 9 +- src/units.cpp | 107 ++++++++++---------- src/units.h | 10 +- src/utils/path.cpp | 153 +++++++++++++++++++++++++++++ src/utils/path.h | 42 ++++++++ 27 files changed, 913 insertions(+), 550 deletions(-) create mode 100644 src/resources/settingsmanager.cpp create mode 100644 src/resources/settingsmanager.h create mode 100644 src/utils/path.cpp create mode 100644 src/utils/path.h diff --git a/AUTHORS b/AUTHORS index 031495a5..83a31805 100644 --- a/AUTHORS +++ b/AUTHORS @@ -42,6 +42,7 @@ Marcel W. Wysocki Mateusz Kaduk (Usiu) Matthias Hartmann Philipp Sehmisch (Crush) +Przemysław Grzywacz Roderic Morris (rodge) Rogier Polak Scott Ellis diff --git a/mana.cbp b/mana.cbp index f25a33c4..3d5345d7 100644 --- a/mana.cbp +++ b/mana.cbp @@ -552,6 +552,8 @@ + + @@ -598,6 +600,8 @@ + + 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(mLoginHandler.get())->clearWorlds(); static_cast(mCharHandler.get())->setCharCreateDialog(0); static_cast(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 #include @@ -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 #include -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 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 #include #include +#include "utils/xml.h" class ImageSprite; @@ -42,7 +43,11 @@ typedef std::map 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 #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 or new " - " 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 #include +#include "utils/xml.h" /** * Hair information database. @@ -40,10 +41,11 @@ class HairDB ~HairDB() { unload(); } - /** - * Loads the color data from hair.xml. - */ - 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 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 s - for_each_xml_child_node(monsterNode, rootNode) + SpriteDisplay display; + + //iterate s and 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 s and 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 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 +#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 . + */ + +#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 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 . + */ + +#ifndef SETTINGSMANAGER_HPP +#define SETTINGSMANAGER_HPP + +#include +#include +#include + +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 #include +#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 @@ -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 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 +#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 . + */ + +#include "utils/path.h" +#include + +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 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 . + */ + +#ifndef UTILS_PATH_H +#define UTILS_PATH_H + +#include + +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 -- cgit v1.2.3-70-g09d2 From 92c09d42b782deff9dcb9dcc6b408fdd36bc4f37 Mon Sep 17 00:00:00 2001 From: Przemysław Grzywacz Date: Tue, 7 May 2013 17:45:26 +0200 Subject: items.xml can be used from settings.xml --- src/client.cpp | 24 ++-- src/resources/itemdb.cpp | 284 +++++++++++++++++--------------------- src/resources/itemdb.h | 34 ++--- src/resources/settingsmanager.cpp | 10 +- 4 files changed, 165 insertions(+), 187 deletions(-) diff --git a/src/client.cpp b/src/client.cpp index 0d2c4bca..6b8ebca1 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -761,13 +761,12 @@ int Client::exec() // 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(); + + if (itemDb) + delete itemDb; + switch (Net::getNetworkType()) { case ServerInfo::TMWATHENA: @@ -781,17 +780,10 @@ int Client::exec() itemDb = 0; break; } - if (!itemDb || !itemDb->isLoaded()) - { - // Warn and return to login screen - errorMessage = - _("This server is missing needed world data. " - "Please contact the administrator(s)."); - showOkDialog(_("ItemDB: Error while loading " - ITEMS_DB_FILE "!"), errorMessage, - STATE_CHOOSE_SERVER); - break; - } + assert(itemDb); + + // load settings.xml + SettingsManager::load(); ActorSprite::load(); diff --git a/src/resources/itemdb.cpp b/src/resources/itemdb.cpp index 4db7b085..b802457e 100644 --- a/src/resources/itemdb.cpp +++ b/src/resources/itemdb.cpp @@ -31,7 +31,6 @@ #include "utils/dtor.h" #include "utils/gettext.h" #include "utils/stringutils.h" -#include "utils/xml.h" #include "configuration.h" #include @@ -189,18 +188,17 @@ void ItemDB::unload() mLoaded = false; } -void ItemDB::loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node) +void ItemDB::loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node, const std::string &filename) { int id = XML::getProperty(node, "id", 0); if (!id) { - logger->log("ItemDB: Invalid or missing item Id in " - ITEMS_DB_FILE "!"); + logger->log("ItemDB: Invalid or missing item Id in %s!", filename.c_str()); return; } else if (mItemInfos.find(id) != mItemInfos.end()) - logger->log("ItemDB: Redefinition of item Id %d", id); + logger->log("ItemDB: Redefinition of item Id %d in %s", id, filename.c_str()); int view = XML::getProperty(node, "view", 0); @@ -324,71 +322,60 @@ static char const *const fields[][2] = { "mp", N_("MP %+d") } }; -void TaItemDB::load() +void TaItemDB::init() { if (mLoaded) unload(); - logger->log("Initializing TmwAthena item database..."); - mUnknown = new TaItemInfo; loadEmptyItemDefinition(); +} + +void TaItemDB::readItemNode(xmlNodePtr node, const std::string &filename) +{ + TaItemInfo *itemInfo = new TaItemInfo; - XML::Document doc(ITEMS_DB_FILE); - xmlNodePtr rootNode = doc.rootNode(); + loadCommonRef(itemInfo, node, filename); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items")) + // Everything not unusable or usable is equippable by the Ta type system. + itemInfo->mEquippable = itemInfo->mType != ITEM_UNUSABLE + && itemInfo->mType != ITEM_USABLE; + itemInfo->mActivatable = itemInfo->mType == ITEM_USABLE; + + // Load nano description + std::vector effect; + for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i) { - logger->error("ItemDB: Error while loading " ITEMS_DB_FILE "!"); - return; + int value = XML::getProperty(node, fields[i][0], 0); + if (!value) + continue; + effect.push_back(strprintf(gettext(fields[i][1]), value)); } - - for_each_xml_child_node(node, rootNode) + for (std::list::iterator it = extraStats.begin(); + it != extraStats.end(); it++) { - if (!xmlStrEqual(node->name, BAD_CAST "item")) + int value = XML::getProperty(node, it->mTag.c_str(), 0); + if (!value) continue; + effect.push_back(strprintf(it->mFormat.c_str(), value)); + } + std::string temp = XML::getProperty(node, "effect", ""); + if (!temp.empty()) + effect.push_back(temp); - TaItemInfo *itemInfo = new TaItemInfo; - - loadCommonRef(itemInfo, node); - - // Everything not unusable or usable is equippable by the Ta type system. - itemInfo->mEquippable = itemInfo->mType != ITEM_UNUSABLE - && itemInfo->mType != ITEM_USABLE; - itemInfo->mActivatable = itemInfo->mType == ITEM_USABLE; - - // Load nano description - std::vector effect; - for (int i = 0; i < int(sizeof(fields) / sizeof(fields[0])); ++i) - { - int value = XML::getProperty(node, fields[i][0], 0); - if (!value) - continue; - effect.push_back(strprintf(gettext(fields[i][1]), value)); - } - for (std::list::iterator it = extraStats.begin(); - it != extraStats.end(); it++) - { - int value = XML::getProperty(node, it->mTag.c_str(), 0); - if (!value) - continue; - effect.push_back(strprintf(it->mFormat.c_str(), value)); - } - std::string temp = XML::getProperty(node, "effect", ""); - if (!temp.empty()) - effect.push_back(temp); - - itemInfo->mEffect = effect; + itemInfo->mEffect = effect; - checkItemInfo(itemInfo); + checkItemInfo(itemInfo); - addItem(itemInfo); + addItem(itemInfo); - // Insert hairstyle id while letting the info as an item. - if (itemInfo->mType == ITEM_SPRITE_HAIR) - hairDB.addHairStyle(itemInfo->mId); - } + // Insert hairstyle id while letting the info as an item. + if (itemInfo->mType == ITEM_SPRITE_HAIR) + hairDB.addHairStyle(itemInfo->mId); +} +void TaItemDB::checkStatus() +{ checkHairWeaponsRacesSpecialIds(); mLoaded = true; @@ -423,7 +410,7 @@ static void initTriggerTable() } } -void ManaServItemDB::load() +void ManaServItemDB::init() { if (mLoaded) unload(); @@ -431,129 +418,118 @@ void ManaServItemDB::load() // Initialize the trigger table for effect descriptions initTriggerTable(); - logger->log("Initializing ManaServ item database..."); - mUnknown = new ManaServItemInfo; loadEmptyItemDefinition(); +} - XML::Document doc(ITEMS_DB_FILE); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items")) - { - logger->log("ItemDB: Error while loading " ITEMS_DB_FILE "!"); - return; - } - - for_each_xml_child_node(node, rootNode) - { - if (!xmlStrEqual(node->name, BAD_CAST "item")) - continue; - - ManaServItemInfo *itemInfo = new ManaServItemInfo; +void ManaServItemDB::readItemNode(xmlNodePtr node, const std::string &filename) +{ + ManaServItemInfo *itemInfo = new ManaServItemInfo; - loadCommonRef(itemInfo, node); + loadCommonRef(itemInfo, node, filename); - // We default eqippable and activatable to false as their actual value will be set - // within the and sub-nodes.. - itemInfo->mActivatable = false; - itemInfo->mEquippable = false; + // We default eqippable and activatable to false as their actual value will be set + // within the and sub-nodes.. + itemInfo->mActivatable = false; + itemInfo->mEquippable = false; - // Load , and sub nodes. - std::vector effect; - for_each_xml_child_node(itemChild, node) + // Load , and sub nodes. + std::vector effect; + for_each_xml_child_node(itemChild, node) + { + if (xmlStrEqual(itemChild->name, BAD_CAST "equip")) { - if (xmlStrEqual(itemChild->name, BAD_CAST "equip")) + // The fact that there is a way to equip is enough. + // Discard any details, but mark the item as equippable. + itemInfo->mEquippable = true; + } + else if (xmlStrEqual(itemChild->name, BAD_CAST "effect")) + { + std::string trigger = XML::getProperty( + itemChild, "trigger", ""); + if (trigger.empty()) { - // The fact that there is a way to equip is enough. - // Discard any details, but mark the item as equippable. - itemInfo->mEquippable = true; + logger->log("Found empty trigger effect label in %s, skipping.", filename.c_str()); + continue; } - else if (xmlStrEqual(itemChild->name, BAD_CAST "effect")) - { - std::string trigger = XML::getProperty( - itemChild, "trigger", ""); - if (trigger.empty()) - { - logger->log("Found empty trigger effect label, skipping."); - continue; - } - if (trigger == "activation") - itemInfo->mActivatable = true; + if (trigger == "activation") + itemInfo->mActivatable = true; - std::map::const_iterator triggerLabel = - triggerTable.find(trigger); - if (triggerLabel == triggerTable.end()) - { - logger->log("Warning: unknown trigger %s in item %d!", - trigger.c_str(), itemInfo->mId); - continue; - } + std::map::const_iterator triggerLabel = + triggerTable.find(trigger); + if (triggerLabel == triggerTable.end()) + { + logger->log("Warning: unknown trigger %s in item %d!", + trigger.c_str(), itemInfo->mId); + continue; + } - for_each_xml_child_node(effectChild, itemChild) + for_each_xml_child_node(effectChild, itemChild) + { + if (xmlStrEqual(effectChild->name, BAD_CAST "modifier")) { - if (xmlStrEqual(effectChild->name, BAD_CAST "modifier")) + std::string attribute = XML::getProperty( + effectChild, "attribute", ""); + double value = XML::getFloatProperty( + effectChild, "value", 0.0); + int duration = XML::getProperty( + effectChild, "duration", 0); + if (attribute.empty() || !value) + { + logger->log("Warning: incomplete modifier definition in %s, skipping.", filename.c_str()); + continue; + } + std::list::const_iterator + it = extraStats.begin(), + it_end = extraStats.end(); + while (it != it_end && !(*it == attribute)) + ++it; + if (it == extraStats.end()) { - std::string attribute = XML::getProperty( - effectChild, "attribute", ""); - double value = XML::getFloatProperty( - effectChild, "value", 0.0); - int duration = XML::getProperty( - effectChild, "duration", 0); - if (attribute.empty() || !value) - { - logger->log("Warning: incomplete modifier definition, skipping."); - continue; - } - std::list::const_iterator - it = extraStats.begin(), - it_end = extraStats.end(); - while (it != it_end && !(*it == attribute)) - ++it; - if (it == extraStats.end()) - { - logger->log("Warning: unknown modifier tag %s, skipping.", attribute.c_str()); - continue; - } - effect.push_back( - strprintf(strprintf( - duration ? - strprintf("%%s%%s. This effect lasts %d ticks.", duration).c_str() - : "%s%s.", it->mFormat.c_str(), triggerLabel->second).c_str(), value)); + logger->log("Warning: unknown modifier tag %s in %s, skipping.", attribute.c_str(), filename.c_str()); + continue; } - else if (xmlStrEqual(effectChild->name, BAD_CAST "modifier")) - effect.push_back(strprintf("Provides an autoattack%s.", - triggerLabel->second)); - else if (xmlStrEqual(effectChild->name, BAD_CAST "consumes")) - effect.push_back(strprintf("This will be consumed%s.", - triggerLabel->second)); - else if (xmlStrEqual(effectChild->name, BAD_CAST "label")) - effect.push_back( - (const char*)effectChild->xmlChildrenNode->content); + effect.push_back( + strprintf(strprintf( + duration ? + strprintf("%%s%%s. This effect lasts %d ticks.", duration).c_str() + : "%s%s.", it->mFormat.c_str(), triggerLabel->second).c_str(), value)); } + else if (xmlStrEqual(effectChild->name, BAD_CAST "modifier")) + effect.push_back(strprintf("Provides an autoattack%s.", + triggerLabel->second)); + else if (xmlStrEqual(effectChild->name, BAD_CAST "consumes")) + effect.push_back(strprintf("This will be consumed%s.", + triggerLabel->second)); + else if (xmlStrEqual(effectChild->name, BAD_CAST "label")) + effect.push_back( + (const char*)effectChild->xmlChildrenNode->content); } + } - // FIXME: Load hair styles through the races.xml file - if (itemInfo->mType == ITEM_SPRITE_HAIR) - hairDB.addHairStyle(itemInfo->mId); + // FIXME: Load hair styles through the races.xml file + if (itemInfo->mType == ITEM_SPRITE_HAIR) + hairDB.addHairStyle(itemInfo->mId); - // Set Item Type based on subnodes info - // TODO: Improve it once the itemTypes are loaded through xml - itemInfo->mType = ITEM_UNUSABLE; - if (itemInfo->mActivatable) - itemInfo->mType = ITEM_USABLE; - else if (itemInfo->mEquippable) - itemInfo->mType = ITEM_EQUIPMENT_TORSO; - } // end for_each_xml_child_node(itemChild, node) + // Set Item Type based on subnodes info + // TODO: Improve it once the itemTypes are loaded through xml + itemInfo->mType = ITEM_UNUSABLE; + if (itemInfo->mActivatable) + itemInfo->mType = ITEM_USABLE; + else if (itemInfo->mEquippable) + itemInfo->mType = ITEM_EQUIPMENT_TORSO; + } // end for_each_xml_child_node(itemChild, node) - itemInfo->mEffect = effect; + itemInfo->mEffect = effect; - checkItemInfo(itemInfo); + checkItemInfo(itemInfo); - addItem(itemInfo); - } + addItem(itemInfo); +} +void ManaServItemDB::checkStatus() +{ mLoaded = true; } diff --git a/src/resources/itemdb.h b/src/resources/itemdb.h index d7859ad3..2f19339d 100644 --- a/src/resources/itemdb.h +++ b/src/resources/itemdb.h @@ -81,11 +81,6 @@ class ItemDB virtual ~ItemDB() {} - /** - * Loads the item data from items.xml. - */ - virtual void load() = 0; - /** * Frees item data. */ @@ -102,12 +97,18 @@ class ItemDB const ItemInfo &get(int id); const ItemInfo &get(const std::string &name); + virtual void init() = 0; + + virtual void readItemNode(xmlNodePtr node, const std::string &filename) = 0; + + virtual void checkStatus() = 0; + protected: /** * Permits to load item definitions which are common * for each protocols to avoid code duplication. */ - void loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node); + void loadCommonRef(ItemInfo *itemInfo, xmlNodePtr node, const std::string &filename); /** * Checks the items parameters consistency. @@ -164,16 +165,16 @@ class TaItemDB: public ItemDB { public: TaItemDB() : ItemDB() - { load(); } + { } ~TaItemDB() { unload(); } - /** - * Loads the item data from items.xml. - */ - void load(); + virtual void init(); + + virtual void readItemNode(xmlNodePtr node, const std::string &filename); + virtual void checkStatus(); private: /** * Check items id specific hard limits and log errors found. @@ -198,15 +199,16 @@ class ManaServItemDB: public ItemDB { public: ManaServItemDB() : ItemDB() - { load(); } + { } ~ManaServItemDB() { unload(); } - /** - * Loads the item data from items.xml. - */ - void load(); + virtual void init(); + + virtual void readItemNode(xmlNodePtr node, const std::string &filename); + + virtual void checkStatus(); private: void checkItemInfo(ItemInfo* itemInfo); diff --git a/src/resources/settingsmanager.cpp b/src/resources/settingsmanager.cpp index 3cbb115c..b2d1fe80 100644 --- a/src/resources/settingsmanager.cpp +++ b/src/resources/settingsmanager.cpp @@ -21,8 +21,9 @@ #include "resources/settingsmanager.h" #include "resources/attributes.h" -#include "resources/monsterdb.h" #include "resources/hairdb.h" +#include "resources/itemdb.h" +#include "resources/monsterdb.h" #include "resources/specialdb.h" #include "resources/npcdb.h" #include "resources/emotedb.h" @@ -48,6 +49,7 @@ namespace SettingsManager // initialize managers Attributes::init(); hairDB.init(); + itemDb->init(); MonsterDB::init(); SpecialDB::init(); NPCDB::init(); @@ -60,6 +62,7 @@ namespace SettingsManager Attributes::checkStatus(); hairDB.checkStatus(); + itemDb->checkStatus(); MonsterDB::checkStatus(); SpecialDB::checkStatus(); NPCDB::checkStatus(); @@ -80,6 +83,7 @@ namespace SettingsManager NPCDB::unload(); SpecialDB::unload(); MonsterDB::unload(); + itemDb->unload(); hairDB.unload(); Attributes::unload(); } @@ -149,6 +153,10 @@ namespace SettingsManager { hairDB.readHairColorNode(childNode, filename); } + else if (xmlStrEqual(childNode->name, BAD_CAST "item")) + { + itemDb->readItemNode(childNode, filename); + } else if (xmlStrEqual(childNode->name, BAD_CAST "monster")) { MonsterDB::readMonsterNode(childNode, filename); -- cgit v1.2.3-70-g09d2 From 64520d5f1f3c124435797fccae9b68be69e04133 Mon Sep 17 00:00:00 2001 From: Thorbjørn Lindeijer Date: Thu, 9 May 2013 12:43:36 +0200 Subject: Changed default serverlist.xml URL to avoid redirect Previously the redirect was from www.manasource.org to manasource.org. --- docs/example.mana | 2 +- src/gui/serverdialog.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/example.mana b/docs/example.mana index 9173efb0..a79471d4 100644 --- a/docs/example.mana +++ b/docs/example.mana @@ -13,7 +13,7 @@ filename / path as a command line parameter