From 647cebfdf11c2482e5b4bbaad4aa411cdd4bb2cc Mon Sep 17 00:00:00 2001 From: Przemysław Grzywacz Date: Sun, 28 Apr 2013 16:15:20 +0200 Subject: Single xml solution Mana-mantis: #506. --- src/CMakeLists.txt | 2 + src/common/defines.h | 8 +- src/common/resourcemanager.cpp | 107 +++++++++ src/common/resourcemanager.h | 4 + src/game-server/attributemanager.cpp | 103 ++++---- src/game-server/attributemanager.h | 11 +- src/game-server/emotemanager.cpp | 44 ++-- src/game-server/emotemanager.h | 10 +- src/game-server/itemmanager.cpp | 134 ++++------- src/game-server/itemmanager.h | 18 +- src/game-server/main-game.cpp | 28 ++- src/game-server/monstermanager.cpp | 453 +++++++++++++++++------------------ src/game-server/monstermanager.h | 11 +- src/game-server/settingsmanager.cpp | 191 +++++++++++++++ src/game-server/settingsmanager.h | 51 ++++ src/game-server/skillmanager.cpp | 53 ++-- src/game-server/skillmanager.h | 13 +- src/game-server/specialmanager.cpp | 72 +++--- src/game-server/specialmanager.h | 9 +- src/game-server/statusmanager.cpp | 124 +++++----- src/game-server/statusmanager.h | 7 +- 21 files changed, 884 insertions(+), 569 deletions(-) create mode 100644 src/game-server/settingsmanager.cpp create mode 100644 src/game-server/settingsmanager.h (limited to 'src') diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8fc5f6e..5a92e29 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -253,6 +253,8 @@ SET(SRCS_MANASERVGAME game-server/postman.h game-server/quest.h game-server/quest.cpp + game-server/settingsmanager.h + game-server/settingsmanager.cpp game-server/skillmanager.h game-server/skillmanager.cpp game-server/spawnareacomponent.h diff --git a/src/common/defines.h b/src/common/defines.h index 4ba77a1..40be064 100644 --- a/src/common/defines.h +++ b/src/common/defines.h @@ -30,16 +30,10 @@ #define WORLD_TICK_MS 100 // Files +#define DEFAULT_SETTINGS_FILE "settings.xml" #define DEFAULT_MAPSDB_FILE "maps.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" -#define DEFAULT_EQUIPDB_FILE "equip.xml" -#define DEFAULT_SKILLSDB_FILE "skills.xml" -#define DEFAULT_ATTRIBUTEDB_FILE "attributes.xml" -#define DEFAULT_MONSTERSDB_FILE "monsters.xml" -#define DEFAULT_STATUSDB_FILE "status-effects.xml" #define DEFAULT_PERMISSION_FILE "permissions.xml" -#define DEFAULT_SPECIALSDB_FILE "specials.xml" -#define DEFAULT_EMOTESDB_FILE "emotes.xml" /** * Exit value codes are thrown back at servers exit to reflect their exit state. diff --git a/src/common/resourcemanager.cpp b/src/common/resourcemanager.cpp index 92a8591..82675c7 100644 --- a/src/common/resourcemanager.cpp +++ b/src/common/resourcemanager.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #ifdef _WIN32 #include @@ -133,3 +134,109 @@ ResourceManager::splittedPath ResourceManager::splitFileNameAndPath( 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 ResourceManager::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 ResourceManager::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/common/resourcemanager.h b/src/common/resourcemanager.h index 569428d..eea701a 100644 --- a/src/common/resourcemanager.h +++ b/src/common/resourcemanager.h @@ -67,6 +67,10 @@ namespace ResourceManager * and the file name alone. */ 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 diff --git a/src/game-server/attributemanager.cpp b/src/game-server/attributemanager.cpp index 42c2624..f71f4fa 100644 --- a/src/game-server/attributemanager.cpp +++ b/src/game-server/attributemanager.cpp @@ -35,43 +35,6 @@ void AttributeManager::reload() mAttributeMap.clear(); for (unsigned i = 0; i < MaxScope; ++i) mAttributeScopes[i].clear(); - - readAttributesFile(); - - LOG_DEBUG("attribute map:"); - LOG_DEBUG("Stackable is " << Stackable << ", NonStackable is " << NonStackable - << ", NonStackableBonus is " << NonStackableBonus << "."); - LOG_DEBUG("Additive is " << Additive << ", Multiplicative is " << Multiplicative << "."); - const std::string *tag; - unsigned count = 0; - for (AttributeMap::const_iterator i = mAttributeMap.begin(); - i != mAttributeMap.end(); ++i) - { - unsigned lCount = 0; - LOG_DEBUG(" "<first<<" : "); - for (std::vector::const_iterator j = - i->second.modifiers.begin(); - j != i->second.modifiers.end(); ++j) - { - tag = getTag(ModifierLocation(i->first, lCount)); - std::string end = tag ? "tag of '" + (*tag) + "'." : "no tag."; - LOG_DEBUG(" stackableType: " << j->stackableType - << ", effectType: " << j->effectType << ", and " << end); - ++lCount; - ++count; - } - } - LOG_INFO("Loaded '" << mAttributeMap.size() << "' attributes with '" - << count << "' modifier layers."); - - for (TagMap::const_iterator i = mTagMap.begin(), i_end = mTagMap.end(); - i != i_end; ++i) - { - LOG_DEBUG("Tag '" << i->first << "': '" << i->second.attributeId - << "', '" << i->second.layer << "'."); - } - - LOG_INFO("Loaded '" << mTagMap.size() << "' modifier tags."); } const std::vector *AttributeManager::getAttributeInfo(int id) const @@ -112,27 +75,10 @@ const std::string *AttributeManager::getTag(const ModifierLocation &location) co return 0; } -void AttributeManager::readAttributesFile() -{ - XML::Document doc(mAttributeReferenceFile); - xmlNodePtr node = doc.rootNode(); - - if (!node || !xmlStrEqual(node->name, BAD_CAST "attributes")) - { - LOG_FATAL("Attribute Manager: " << mAttributeReferenceFile - << " is not a valid database file!"); - exit(EXIT_XML_BAD_PARAMETER); - } - - LOG_INFO("Loading attribute reference..."); - - for_each_xml_child_node(childNode, node) - { - if (xmlStrEqual(childNode->name, BAD_CAST "attribute")) - readAttributeNode(childNode); - } -} - +/** + * Read a element from settings. + * Used by SettingsManager. + */ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) { int id = XML::getProperty(attributeNode, "id", 0); @@ -196,6 +142,47 @@ void AttributeManager::readAttributeNode(xmlNodePtr attributeNode) } } +/** + * Check the status of recently loaded configuration. + */ +void AttributeManager::checkStatus() +{ + LOG_DEBUG("attribute map:"); + LOG_DEBUG("Stackable is " << Stackable << ", NonStackable is " << NonStackable + << ", NonStackableBonus is " << NonStackableBonus << "."); + LOG_DEBUG("Additive is " << Additive << ", Multiplicative is " << Multiplicative << "."); + const std::string *tag; + unsigned count = 0; + for (AttributeMap::const_iterator i = mAttributeMap.begin(); + i != mAttributeMap.end(); ++i) + { + unsigned lCount = 0; + LOG_DEBUG(" "<first<<" : "); + for (std::vector::const_iterator j = + i->second.modifiers.begin(); + j != i->second.modifiers.end(); ++j) + { + tag = getTag(ModifierLocation(i->first, lCount)); + std::string end = tag ? "tag of '" + (*tag) + "'." : "no tag."; + LOG_DEBUG(" stackableType: " << j->stackableType + << ", effectType: " << j->effectType << ", and " << end); + ++lCount; + ++count; + } + } + LOG_INFO("Loaded '" << mAttributeMap.size() << "' attributes with '" + << count << "' modifier layers."); + + for (TagMap::const_iterator i = mTagMap.begin(), i_end = mTagMap.end(); + i != i_end; ++i) + { + LOG_DEBUG("Tag '" << i->first << "': '" << i->second.attributeId + << "', '" << i->second.layer << "'."); + } + + LOG_INFO("Loaded '" << mTagMap.size() << "' modifier tags."); +} + void AttributeManager::readModifierNode(xmlNodePtr modifierNode, int attributeId) { diff --git a/src/game-server/attributemanager.h b/src/game-server/attributemanager.h index 1a55006..9bc40e1 100644 --- a/src/game-server/attributemanager.h +++ b/src/game-server/attributemanager.h @@ -105,8 +105,7 @@ class AttributeManager std::vector modifiers; }; - AttributeManager(const std::string &file) : - mAttributeReferenceFile(file) + AttributeManager() {} /** @@ -132,9 +131,11 @@ class AttributeManager const std::string *getTag(const ModifierLocation &location) const; - private: - void readAttributesFile(); void readAttributeNode(xmlNodePtr attributeNode); + + void checkStatus(); + + private: void readModifierNode(xmlNodePtr modifierNode, int attributeId); // Attribute id -> { modifiable, min, max, { stackable type, effect type }[] } @@ -146,8 +147,6 @@ class AttributeManager AttributeScope mAttributeScopes[MaxScope]; AttributeMap mAttributeMap; TagMap mTagMap; - - const std::string mAttributeReferenceFile; }; extern AttributeManager *attributeManager; diff --git a/src/game-server/emotemanager.cpp b/src/game-server/emotemanager.cpp index 35f0aa4..c412854 100644 --- a/src/game-server/emotemanager.cpp +++ b/src/game-server/emotemanager.cpp @@ -26,37 +26,39 @@ void EmoteManager::initialize() { clear(); +} - XML::Document doc(mEmoteFile); - xmlNodePtr rootNode = doc.rootNode(); +void EmoteManager::reload() +{ + clear(); +} - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "emotes")) +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void EmoteManager::readEmoteNode(xmlNodePtr node, const std::string &filename) +{ + int id = XML::getProperty(node, "id", -1); + if (id < 0) { - LOG_ERROR("Emote Manager: " << mEmoteFile - << " is not a valid emote file!"); + LOG_WARN("The " << filename << " file is containing an invalid id" + "(" << id << ") and will be ignored."); return; } - LOG_INFO("Loading emote reference: " << mEmoteFile); - - for_each_xml_child_node(emoteNode, rootNode) - { - if (!xmlStrEqual(emoteNode->name, BAD_CAST "emote")) - continue; - - int id = XML::getProperty(emoteNode, "id", -1); - if (id < 0) - { - LOG_WARN("The " << mEmoteFile << " file is containing an invalid id" - "(" << id << ") and will be ignored."); - continue; - } + mEmoteIds.push_back(id); +} - mEmoteIds.push_back(id); - } +/** + * Check the status of recently loaded configuration. + */ +void EmoteManager::checkStatus() +{ LOG_INFO(mEmoteIds.size() << " emotes available."); } + bool EmoteManager::isIdAvailable(int id) const { std::vector::const_iterator it = mEmoteIds.begin(); diff --git a/src/game-server/emotemanager.h b/src/game-server/emotemanager.h index 42c7168..9470132 100644 --- a/src/game-server/emotemanager.h +++ b/src/game-server/emotemanager.h @@ -31,8 +31,7 @@ class EmoteManager { public: - EmoteManager(const std::string &emoteFile): - mEmoteFile(emoteFile) + EmoteManager() { } ~EmoteManager() @@ -43,11 +42,17 @@ public: */ void initialize(); + void reload(); + /** * Tells whether the given id is a valid emote one. */ bool isIdAvailable(int id) const; + void readEmoteNode(xmlNodePtr node, const std::string &filename); + + void checkStatus(); + private: /** * Clears up the emote list. @@ -55,7 +60,6 @@ private: void clear() { mEmoteIds.clear(); } - std::string mEmoteFile; std::vector mEmoteIds; }; diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index 504ba12..05dd0d0 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -42,8 +42,6 @@ void ItemManager::reload() void ItemManager::initialize() { mVisibleEquipSlotCount = 0; - readEquipSlotsFile(); - readItemsFile(); } void ItemManager::deinitialize() @@ -99,111 +97,75 @@ bool ItemManager::isEquipSlotVisible(unsigned id) const return i != mEquipSlotsInfo.end() ? i->second->visibleSlot : false; } -void ItemManager::readEquipSlotsFile() + +/** + * Check the status of recently loaded configuration. + */ +void ItemManager::checkStatus() +{ + LOG_INFO("Loaded " << mItemClasses.size() << " items"); + LOG_INFO("Loaded " << mEquipSlotsInfo.size() << " slot types"); +} + +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void ItemManager::readEquipSlotNode(xmlNodePtr node) { - XML::Document doc(mEquipSlotsFile); - xmlNodePtr rootNode = doc.rootNode(); + const int slotId = XML::getProperty(node, "id", 0); + const std::string name = XML::getProperty(node, "name", + std::string()); + const int capacity = XML::getProperty(node, "capacity", 0); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equip-slots")) + if (slotId <= 0 || name.empty() || capacity <= 0) { - LOG_ERROR("Item Manager: Error while parsing equip slots database (" - << mEquipSlotsFile << ")!"); + LOG_WARN("Item Manager: equip slot " << slotId + << ": (" << name << ") has no name or zero count. " + "The slot has been ignored."); return; } - LOG_INFO("Loading equip slots: " << mEquipSlotsFile); - - unsigned totalCapacity = 0; - unsigned slotCount = 0; - mVisibleEquipSlotCount = 0; - - for_each_xml_child_node(node, rootNode) + if (slotId > 255) { - if (xmlStrEqual(node->name, BAD_CAST "slot")) - { - const int slotId = XML::getProperty(node, "id", 0); - const std::string name = XML::getProperty(node, "name", - std::string()); - const int capacity = XML::getProperty(node, "capacity", 0); - - if (slotId <= 0 || name.empty() || capacity <= 0) - { - LOG_WARN("Item Manager: equip slot " << slotId - << ": (" << name << ") has no name or zero count. " - "The slot has been ignored."); - continue; - } - - if (slotId > 255) - { - LOG_WARN("Item Manager: equip slot " << slotId - << ": (" << name << ") is superior to 255 " - "and has been ignored."); - continue; - } - - bool visible = XML::getBoolProperty(node, "visible", false); - if (visible) - ++mVisibleEquipSlotCount; - - EquipSlotsInfo::iterator i = mEquipSlotsInfo.find(slotId); - - if (i != mEquipSlotsInfo.end()) - { - LOG_WARN("Item Manager: Ignoring duplicate definition " - "of equip slot '" << slotId << "'!"); - continue; - } - - LOG_DEBUG("Adding equip slot, id: " << slotId << ", name: " << name - << ", capacity: " << capacity << ", visible? " << visible); - EquipSlotInfo *equipSlotInfo = - new EquipSlotInfo(slotId, name, capacity, visible); - mEquipSlotsInfo.insert(std::make_pair(slotId, equipSlotInfo)); - mNamedEquipSlotsInfo.insert(name, equipSlotInfo); - - totalCapacity += capacity; - ++slotCount; - } + LOG_WARN("Item Manager: equip slot " << slotId + << ": (" << name << ") is superior to 255 " + "and has been ignored."); + return; } - LOG_INFO("Loaded '" << slotCount << "' slot types with '" - << totalCapacity << "' slots."); -} + bool visible = XML::getBoolProperty(node, "visible", false); + if (visible) + ++mVisibleEquipSlotCount; -void ItemManager::readItemsFile() -{ - XML::Document doc2(mItemsFile); - xmlNodePtr rootNode = doc2.rootNode(); + EquipSlotsInfo::iterator i = mEquipSlotsInfo.find(slotId); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "items")) + if (i != mEquipSlotsInfo.end()) { - LOG_ERROR("Item Manager: Error while parsing item database (" - << mItemsFile << ")!"); + LOG_WARN("Item Manager: Ignoring duplicate definition " + "of equip slot '" << slotId << "'!"); return; } - LOG_INFO("Loading item reference: " << mItemsFile); - - for_each_xml_child_node(node, rootNode) - { - if (xmlStrEqual(node->name, BAD_CAST "item")) - { - readItemNode(node); - } - } - - LOG_INFO("Loaded " << mItemClasses.size() << " items from " - << mItemsFile << "."); + LOG_DEBUG("Adding equip slot, id: " << slotId << ", name: " << name + << ", capacity: " << capacity << ", visible? " << visible); + EquipSlotInfo *equipSlotInfo = + new EquipSlotInfo(slotId, name, capacity, visible); + mEquipSlotsInfo.insert(std::make_pair(slotId, equipSlotInfo)); + mNamedEquipSlotsInfo.insert(name, equipSlotInfo); } -void ItemManager::readItemNode(xmlNodePtr itemNode) +/** + * Read an element from settings. + * Used by SettingsManager. + */ +void ItemManager::readItemNode(xmlNodePtr itemNode, const std::string &filename) { const int id = XML::getProperty(itemNode, "id", 0); if (id < 1) { LOG_WARN("Item Manager: Item ID: " << id << " is invalid in " - << mItemsFile << ", and will be ignored."); + << filename << ", and will be ignored."); return; } @@ -225,7 +187,7 @@ void ItemManager::readItemNode(xmlNodePtr itemNode) if (!maxPerSlot) { LOG_WARN("Item Manager: Missing max-per-slot property for " - "item " << id << " in " << mItemsFile << '.'); + "item " << id << " in " << filename << '.'); maxPerSlot = 1; } diff --git a/src/game-server/itemmanager.h b/src/game-server/itemmanager.h index 6a1f459..ac3c0b8 100644 --- a/src/game-server/itemmanager.h +++ b/src/game-server/itemmanager.h @@ -51,9 +51,7 @@ struct EquipSlotInfo class ItemManager { public: - ItemManager(const std::string &itemFile, const std::string &equipFile) : - mItemsFile(itemFile), - mEquipSlotsFile(equipFile), + ItemManager() : mVisibleEquipSlotCount(0), mItemDatabaseVersion(0) {} @@ -103,13 +101,13 @@ class ItemManager bool isEquipSlotVisible(unsigned id) const; - private: - /** Loads the equip slots that a character has available to them. */ - void readEquipSlotsFile(); + void readItemNode(xmlNodePtr itemNode, const std::string &filename); + + void readEquipSlotNode(xmlNodePtr node); - /** Loads the main item database. */ - void readItemsFile(); - void readItemNode(xmlNodePtr itemNode); + void checkStatus(); + + private: void readEquipNode(xmlNodePtr equipNode, ItemClass *item); void readEffectNode(xmlNodePtr effectNode, ItemClass *item); @@ -127,8 +125,6 @@ class ItemManager // We only keep a pointer to it: The id map will take care of deletion. utils::NameMap mNamedEquipSlotsInfo; - std::string mItemsFile; - std::string mEquipSlotsFile; unsigned mVisibleEquipSlotCount; // Cache /** Version of the loaded items database file.*/ diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 8866a39..e21b1dd 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -35,6 +35,7 @@ #include "game-server/statusmanager.h" #include "game-server/postman.h" #include "game-server/state.h" +#include "game-server/settingsmanager.h" #include "net/bandwidth.h" #include "net/connectionhandler.h" #include "net/messageout.h" @@ -77,12 +78,14 @@ static bool running = true; /**< Whether the server keeps running */ utils::StringFilter *stringFilter; /**< Slang's Filter */ -AttributeManager *attributeManager = new AttributeManager(DEFAULT_ATTRIBUTEDB_FILE); -ItemManager *itemManager = new ItemManager(DEFAULT_ITEMSDB_FILE, DEFAULT_EQUIPDB_FILE); -MonsterManager *monsterManager = new MonsterManager(DEFAULT_MONSTERSDB_FILE); -SkillManager *skillManager = new SkillManager(DEFAULT_SKILLSDB_FILE); -SpecialManager *specialManager = new SpecialManager(DEFAULT_SPECIALSDB_FILE); -EmoteManager *emoteManager = new EmoteManager(DEFAULT_EMOTESDB_FILE); +AttributeManager *attributeManager = new AttributeManager(); +ItemManager *itemManager = new ItemManager(); +MonsterManager *monsterManager = new MonsterManager(); +SkillManager *skillManager = new SkillManager(); +SpecialManager *specialManager = new SpecialManager(); +EmoteManager *emoteManager = new EmoteManager(); + +SettingsManager *settingsManager = new SettingsManager(DEFAULT_SETTINGS_FILE); /** Core game message handler */ GameHandler *gameHandler; @@ -130,15 +133,13 @@ static void initializeServer() LOG_FATAL("The Game Server can't find any valid/available maps."); exit(EXIT_MAP_FILE_NOT_FOUND); } - attributeManager->initialize(); - skillManager->initialize(); - specialManager->initialize(); - itemManager->initialize(); - monsterManager->initialize(); - emoteManager->initialize(); - StatusManager::initialize(DEFAULT_STATUSDB_FILE); + + // load game settings files + settingsManager->initialize(); + PermissionManager::initialize(DEFAULT_PERMISSION_FILE); + std::string mainScript = Configuration::getValue("script_mainFile", DEFAULT_MAIN_SCRIPT_FILE); ScriptManager::loadMainScript(mainScript); @@ -192,6 +193,7 @@ static void deinitializeServer() delete skillManager; skillManager = 0; delete itemManager; itemManager = 0; delete emoteManager; emoteManager = 0; + delete settingsManager; settingsManager = 0; MapManager::deinitialize(); StatusManager::deinitialize(); ScriptManager::deinitialize(); diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp index bb29bab..3a9d791 100644 --- a/src/game-server/monstermanager.cpp +++ b/src/game-server/monstermanager.cpp @@ -26,7 +26,6 @@ #include "game-server/itemmanager.h" #include "game-server/monster.h" #include "utils/logger.h" -#include "utils/xml.h" #define MAX_MUTATION 99 #define DEFAULT_MONSTER_SIZE 16 @@ -40,278 +39,276 @@ void MonsterManager::reload() void MonsterManager::initialize() { - XML::Document doc(mMonsterReferenceFile); - xmlNodePtr rootNode = doc.rootNode(); - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "monsters")) +} + +void MonsterManager::deinitialize() +{ + for (MonsterClasses::iterator i = mMonsterClasses.begin(), + i_end = mMonsterClasses.end(); i != i_end; ++i) + { + delete i->second; + } + mMonsterClasses.clear(); + mMonsterClassesByName.clear(); +} + +MonsterClass *MonsterManager::getMonsterByName(const std::string &name) const +{ + return mMonsterClassesByName.value(name); +} + +MonsterClass *MonsterManager::getMonster(int id) const +{ + MonsterClasses::const_iterator i = mMonsterClasses.find(id); + return i != mMonsterClasses.end() ? i->second : 0; +} + +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void MonsterManager::readMonsterNode(xmlNodePtr node, const std::string &filename) +{ + if (!xmlStrEqual(node->name, BAD_CAST "monster")) + return; + + int id = XML::getProperty(node, "id", 0); + std::string name = XML::getProperty(node, "name", std::string()); + + if (id < 1) { - LOG_ERROR("Monster Manager: Error while parsing monster database (" - << mMonsterReferenceFile << ")!"); + LOG_WARN("Monster Manager: Ignoring monster (" + << name << ") without Id in " + << filename << "! It has been ignored."); return; } - LOG_INFO("Loading monster reference: " << mMonsterReferenceFile); - int nbMonsters = 0; - for_each_xml_child_node(node, rootNode) + MonsterClasses::iterator i = mMonsterClasses.find(id); + if (i != mMonsterClasses.end()) { - if (!xmlStrEqual(node->name, BAD_CAST "monster")) - continue; + LOG_WARN("Monster Manager: Ignoring duplicate definition of " + "monster '" << id << "'!"); + return; + } - int id = XML::getProperty(node, "id", 0); - std::string name = XML::getProperty(node, "name", std::string()); + MonsterClass *monster = new MonsterClass(id); + mMonsterClasses[id] = monster; - if (id < 1) - { - LOG_WARN("Monster Manager: Ignoring monster (" - << name << ") without Id in " - << mMonsterReferenceFile << "! It has been ignored."); - continue; - } + if (!name.empty()) + { + monster->setName(name); - MonsterClasses::iterator i = mMonsterClasses.find(id); - if (i != mMonsterClasses.end()) - { - LOG_WARN("Monster Manager: Ignoring duplicate definition of " - "monster '" << id << "'!"); - continue; - } + if (mMonsterClassesByName.contains(name)) + LOG_WARN("Monster Manager: Name not unique for monster " << id); + else + mMonsterClassesByName.insert(name, monster); + } - MonsterClass *monster = new MonsterClass(id); - mMonsterClasses[id] = monster; + MonsterDrops drops; + bool attributesSet = false; + bool behaviorSet = false; - if (!name.empty()) + for_each_xml_child_node(subnode, node) + { + if (xmlStrEqual(subnode->name, BAD_CAST "drop")) { - monster->setName(name); - - if (mMonsterClassesByName.contains(name)) - LOG_WARN("Monster Manager: Name not unique for monster " << id); + MonsterDrop drop; + std::string item = XML::getProperty(subnode, "item", + std::string()); + ItemClass *itemClass; + if (utils::isNumeric(item)) + itemClass = itemManager->getItem(utils::stringToInt(item)); else - mMonsterClassesByName.insert(name, monster); - } + itemClass = itemManager->getItemByName(item); - MonsterDrops drops; - bool attributesSet = false; - bool behaviorSet = false; - - for_each_xml_child_node(subnode, node) - { - if (xmlStrEqual(subnode->name, BAD_CAST "drop")) + if (!itemClass) { - MonsterDrop drop; - std::string item = XML::getProperty(subnode, "item", - std::string()); - ItemClass *itemClass; - if (utils::isNumeric(item)) - itemClass = itemManager->getItem(utils::stringToInt(item)); - else - itemClass = itemManager->getItemByName(item); - - if (!itemClass) - { - LOG_WARN("Monster Manager: Invalid item name \"" << item - << "\""); - break; - } + LOG_WARN("Monster Manager: Invalid item name \"" << item + << "\""); + break; + } - drop.item = itemClass; - drop.probability = XML::getFloatProperty(subnode, "percent", - 0.0) * 100 + 0.5; + drop.item = itemClass; + drop.probability = XML::getFloatProperty(subnode, "percent", + 0.0) * 100 + 0.5; - if (drop.probability) - drops.push_back(drop); - } - else if (xmlStrEqual(subnode->name, BAD_CAST "attributes")) + if (drop.probability) + drops.push_back(drop); + } + else if (xmlStrEqual(subnode->name, BAD_CAST "attributes")) + { + attributesSet = true; + + const int hp = XML::getProperty(subnode, "hp", -1); + monster->setAttribute(ATTR_MAX_HP, hp); + monster->setAttribute(ATTR_HP, hp); + + monster->setAttribute(ATTR_DODGE, + XML::getProperty(subnode, "evade", -1)); + monster->setAttribute(ATTR_MAGIC_DODGE, + XML::getProperty(subnode, "magic-evade", -1)); + monster->setAttribute(ATTR_ACCURACY, + XML::getProperty(subnode, "hit", -1)); + monster->setAttribute(ATTR_DEFENSE, + XML::getProperty(subnode, "physical-defence", -1)); + monster->setAttribute(ATTR_MAGIC_DEFENSE, + XML::getProperty(subnode, "magical-defence", -1)); + monster->setSize(XML::getProperty(subnode, "size", -1)); + float speed = (XML::getFloatProperty(subnode, "speed", -1.0f)); + monster->setMutation(XML::getProperty(subnode, "mutation", 0)); + std::string genderString = XML::getProperty(subnode, "gender", + std::string()); + monster->setGender(getGender(genderString)); + + // Checking attributes for completeness and plausibility + if (monster->getMutation() > MAX_MUTATION) { - attributesSet = true; - - const int hp = XML::getProperty(subnode, "hp", -1); - monster->setAttribute(ATTR_MAX_HP, hp); - monster->setAttribute(ATTR_HP, hp); - - monster->setAttribute(ATTR_DODGE, - XML::getProperty(subnode, "evade", -1)); - monster->setAttribute(ATTR_MAGIC_DODGE, - XML::getProperty(subnode, "magic-evade", -1)); - monster->setAttribute(ATTR_ACCURACY, - XML::getProperty(subnode, "hit", -1)); - monster->setAttribute(ATTR_DEFENSE, - XML::getProperty(subnode, "physical-defence", -1)); - monster->setAttribute(ATTR_MAGIC_DEFENSE, - XML::getProperty(subnode, "magical-defence", -1)); - monster->setSize(XML::getProperty(subnode, "size", -1)); - float speed = (XML::getFloatProperty(subnode, "speed", -1.0f)); - monster->setMutation(XML::getProperty(subnode, "mutation", 0)); - std::string genderString = XML::getProperty(subnode, "gender", - std::string()); - monster->setGender(getGender(genderString)); - - // Checking attributes for completeness and plausibility - if (monster->getMutation() > MAX_MUTATION) - { - LOG_WARN(mMonsterReferenceFile - << ": Mutation of monster Id:" << id << " more than " - << MAX_MUTATION << "%. Defaulted to 0."); - monster->setMutation(0); - } - - bool attributesComplete = true; - const AttributeManager::AttributeScope &mobAttr = - attributeManager->getAttributeScope(MonsterScope); + LOG_WARN(filename + << ": Mutation of monster Id:" << id << " more than " + << MAX_MUTATION << "%. Defaulted to 0."); + monster->setMutation(0); + } - for (AttributeManager::AttributeScope::const_iterator it = - mobAttr.begin(), it_end = mobAttr.end(); it != it_end; ++it) - { - if (!monster->mAttributes.count(it->first)) - { - LOG_WARN(mMonsterReferenceFile << ": No attribute " - << it->first << " for monster Id: " - << id << ". Defaulted to 0."); - attributesComplete = false; - monster->setAttribute(it->first, 0); - } - } + bool attributesComplete = true; + const AttributeManager::AttributeScope &mobAttr = + attributeManager->getAttributeScope(MonsterScope); - if (monster->getSize() == -1) + for (AttributeManager::AttributeScope::const_iterator it = + mobAttr.begin(), it_end = mobAttr.end(); it != it_end; ++it) + { + if (!monster->mAttributes.count(it->first)) { - LOG_WARN(mMonsterReferenceFile - << ": No size set for monster Id:" << id << ". " - << "Defaulted to " << DEFAULT_MONSTER_SIZE - << " pixels."); - monster->setSize(DEFAULT_MONSTER_SIZE); + LOG_WARN(filename << ": No attribute " + << it->first << " for monster Id: " + << id << ". Defaulted to 0."); attributesComplete = false; + monster->setAttribute(it->first, 0); } + } - if (speed == -1.0f) - { - LOG_WARN(mMonsterReferenceFile - << ": No speed set for monster Id:" << id << ". " - << "Defaulted to " << DEFAULT_MONSTER_SPEED - << " tiles/second."); - speed = DEFAULT_MONSTER_SPEED; - attributesComplete = false; - } - monster->setAttribute(ATTR_MOVE_SPEED_TPS, speed); + if (monster->getSize() == -1) + { + LOG_WARN(filename + << ": No size set for monster Id:" << id << ". " + << "Defaulted to " << DEFAULT_MONSTER_SIZE + << " pixels."); + monster->setSize(DEFAULT_MONSTER_SIZE); + attributesComplete = false; + } - if (!attributesComplete) - { - LOG_WARN(mMonsterReferenceFile - << ": Attributes incomplete for monster Id:" << id - << ". Defaults values may have been applied!"); - } + if (speed == -1.0f) + { + LOG_WARN(filename + << ": No speed set for monster Id:" << id << ". " + << "Defaulted to " << DEFAULT_MONSTER_SPEED + << " tiles/second."); + speed = DEFAULT_MONSTER_SPEED; + attributesComplete = false; + } + monster->setAttribute(ATTR_MOVE_SPEED_TPS, speed); + if (!attributesComplete) + { + LOG_WARN(filename + << ": Attributes incomplete for monster Id:" << id + << ". Defaults values may have been applied!"); } - else if (xmlStrEqual(subnode->name, BAD_CAST "exp")) + + } + else if (xmlStrEqual(subnode->name, BAD_CAST "exp")) + { + xmlChar *exp = subnode->xmlChildrenNode->content; + monster->setExp(atoi((const char*)exp)); + monster->setOptimalLevel(XML::getProperty(subnode, "level", 0)); + } + else if (xmlStrEqual(subnode->name, BAD_CAST "behavior")) + { + behaviorSet = true; + if (XML::getBoolProperty(subnode, "aggressive", false)) + monster->setAggressive(true); + + monster->setTrackRange( + XML::getProperty(subnode, "track-range", 1)); + monster->setStrollRange( + XML::getProperty(subnode, "stroll-range", 0)); + monster->setAttackDistance( + XML::getProperty(subnode, "attack-distance", 0)); + } + else if (xmlStrEqual(subnode->name, BAD_CAST "attack")) + { + AttackInfo *att = AttackInfo::readAttackNode(subnode); + bool validMonsterAttack = true; + + if (att->getDamage().id < 1) { - xmlChar *exp = subnode->xmlChildrenNode->content; - monster->setExp(atoi((const char*)exp)); - monster->setOptimalLevel(XML::getProperty(subnode, "level", 0)); + LOG_WARN(filename + << ": Attack without ID for monster Id:" + << id << " (" << name << ") - attack ignored"); + validMonsterAttack = false; } - else if (xmlStrEqual(subnode->name, BAD_CAST "behavior")) + else if (att->getDamage().element == ELEMENT_ILLEGAL) { - behaviorSet = true; - if (XML::getBoolProperty(subnode, "aggressive", false)) - monster->setAggressive(true); - - monster->setTrackRange( - XML::getProperty(subnode, "track-range", 1)); - monster->setStrollRange( - XML::getProperty(subnode, "stroll-range", 0)); - monster->setAttackDistance( - XML::getProperty(subnode, "attack-distance", 0)); + LOG_WARN(filename + << ": Attack with unknown element for monster Id:" + << id << " (" << name << ") - attack ignored"); + validMonsterAttack = false; } - else if (xmlStrEqual(subnode->name, BAD_CAST "attack")) + else if (att->getDamage().type == DAMAGE_OTHER) { - AttackInfo *att = AttackInfo::readAttackNode(subnode); - bool validMonsterAttack = true; - - if (att->getDamage().id < 1) - { - LOG_WARN(mMonsterReferenceFile - << ": Attack without ID for monster Id:" - << id << " (" << name << ") - attack ignored"); - validMonsterAttack = false; - } - else if (att->getDamage().element == ELEMENT_ILLEGAL) - { - LOG_WARN(mMonsterReferenceFile - << ": Attack with unknown element for monster Id:" - << id << " (" << name << ") - attack ignored"); - validMonsterAttack = false; - } - else if (att->getDamage().type == DAMAGE_OTHER) - { - LOG_WARN(mMonsterReferenceFile - << ": Attack with unknown damage type " - << "for monster Id:" << id - << " (" << name << ")"); - validMonsterAttack = false; - } - - if (validMonsterAttack) - { - monster->addAttack(att); - } - else - { - delete att; - att = 0; - } + LOG_WARN(filename + << ": Attack with unknown damage type " + << "for monster Id:" << id + << " (" << name << ")"); + validMonsterAttack = false; + } + if (validMonsterAttack) + { + monster->addAttack(att); } - else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) + else { - Element element = elementFromString( - XML::getProperty(subnode, "element", std::string())); - double factor = XML::getFloatProperty(subnode, "factor", 1.0); - monster->setVulnerability(element, factor); + delete att; + att = 0; } - } - monster->setDrops(drops); - if (!attributesSet) - { - LOG_WARN(mMonsterReferenceFile - << ": No attributes defined for monster Id:" << id - << " (" << name << ")"); - } - if (!behaviorSet) - { - LOG_WARN(mMonsterReferenceFile - << ": No behavior defined for monster Id:" << id - << " (" << name << ")"); } - if (monster->getExp() == -1) + else if (xmlStrEqual(subnode->name, BAD_CAST "vulnerability")) { - LOG_WARN(mMonsterReferenceFile - << ": No experience defined for monster Id:" << id - << " (" << name << ")"); - monster->setExp(0); + Element element = elementFromString( + XML::getProperty(subnode, "element", std::string())); + double factor = XML::getFloatProperty(subnode, "factor", 1.0); + monster->setVulnerability(element, factor); } - ++nbMonsters; } - LOG_INFO("Loaded " << nbMonsters << " monsters from " - << mMonsterReferenceFile << '.'); -} - -void MonsterManager::deinitialize() -{ - for (MonsterClasses::iterator i = mMonsterClasses.begin(), - i_end = mMonsterClasses.end(); i != i_end; ++i) + monster->setDrops(drops); + if (!attributesSet) { - delete i->second; + LOG_WARN(filename + << ": No attributes defined for monster Id:" << id + << " (" << name << ")"); + } + if (!behaviorSet) + { + LOG_WARN(filename + << ": No behavior defined for monster Id:" << id + << " (" << name << ")"); + } + if (monster->getExp() == -1) + { + LOG_WARN(filename + << ": No experience defined for monster Id:" << id + << " (" << name << ")"); + monster->setExp(0); } - mMonsterClasses.clear(); - mMonsterClassesByName.clear(); -} - -MonsterClass *MonsterManager::getMonsterByName(const std::string &name) const -{ - return mMonsterClassesByName.value(name); } -MonsterClass *MonsterManager::getMonster(int id) const +/** + * Check the status of recently loaded configuration. + */ +void MonsterManager::checkStatus() { - MonsterClasses::const_iterator i = mMonsterClasses.find(id); - return i != mMonsterClasses.end() ? i->second : 0; + LOG_INFO("Loaded " << mMonsterClasses.size() << " monsters"); } diff --git a/src/game-server/monstermanager.h b/src/game-server/monstermanager.h index 07ebb58..49a6e83 100644 --- a/src/game-server/monstermanager.h +++ b/src/game-server/monstermanager.h @@ -24,14 +24,15 @@ #include #include #include "utils/string.h" +#include "utils/xml.h" + class MonsterClass; class MonsterManager { public: - MonsterManager(const std::string &file): - mMonsterReferenceFile(file) + MonsterManager() {} ~MonsterManager() @@ -65,13 +66,15 @@ class MonsterManager */ MonsterClass *getMonsterByName(const std::string &name) const; + void readMonsterNode(xmlNodePtr node, const std::string &filename); + + void checkStatus(); + private: typedef std::map< int, MonsterClass * > MonsterClasses; MonsterClasses mMonsterClasses; /**< Monster reference */ utils::NameMap mMonsterClassesByName; - - std::string mMonsterReferenceFile; }; extern MonsterManager *monsterManager; diff --git a/src/game-server/settingsmanager.cpp b/src/game-server/settingsmanager.cpp new file mode 100644 index 0000000..79aade1 --- /dev/null +++ b/src/game-server/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 "game-server/settingsmanager.h" +#include "common/defines.h" +#include "utils/logger.h" +#include "utils/xml.h" + +#include "common/resourcemanager.h" + +#include "game-server/attributemanager.h" +#include "game-server/skillmanager.h" +#include "game-server/specialmanager.h" +#include "game-server/itemmanager.h" +#include "game-server/monstermanager.h" +#include "game-server/emotemanager.h" +#include "game-server/statusmanager.h" + +/** + * Initialize all managers and load configuration into them. + * + * Fatal errors will call exit() + */ +void SettingsManager::initialize() +{ + // initialize all managers in correct order + attributeManager->initialize(); + skillManager->initialize(); + specialManager->initialize(); + itemManager->initialize(); + monsterManager->initialize(); + emoteManager->initialize(); + StatusManager::initialize(); + + loadFile(mSettingsFile); + checkStatus(); +} + +/** + * Reload managers with new configuration. + * + * @note This code is untested, some of the managers didn't even have empty implementations + * of reload(). + */ +void SettingsManager::reload() +{ + attributeManager->reload(); + skillManager->reload(); + specialManager->reload(); + itemManager->reload(); + monsterManager->reload(); + emoteManager->reload(); + StatusManager::reload(); + + loadFile(mSettingsFile); + checkStatus(); +} + +/** + * Load a configuration file. + */ +void SettingsManager::loadFile(const std::string &filename) +{ + LOG_INFO("Loading game settings from " << filename); + + 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") */) + { + LOG_FATAL("Settings Manager: " << filename << " is not a valid database file!"); + exit(EXIT_XML_BAD_PARAMETER); + } + + + // 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 ResourceManager::splittedPath splittedPath = ResourceManager::splitFileNameAndPath(filename); + const std::string realIncludeFile = ResourceManager::cleanPath( + ResourceManager::joinPaths(splittedPath.path, includeFile)); + + // check if we're not entering a loop + if (mIncludedFiles.find(realIncludeFile) != mIncludedFiles.end()) + { + LOG_ERROR("Circular include loop detecting while including " << includeFile << " from " << filename); + } + else + { + // include that file + loadFile(realIncludeFile); + } + } + } + else if (xmlStrEqual(childNode->name, BAD_CAST "attribute")) + { + // attribute config + attributeManager->readAttributeNode(childNode); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "skill-set")) + { + // skills config + skillManager->readSkillSetNode(childNode, filename); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "special-set")) + { + // special config + specialManager->readSpecialSetNode(childNode, filename); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "slot")) + { + // equipement slot config + itemManager->readEquipSlotNode(childNode); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "item")) + { + // item config + itemManager->readItemNode(childNode, filename); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "monster")) + { + // monster config + monsterManager->readMonsterNode(childNode, filename); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "emote")) + { + // emote config + emoteManager->readEmoteNode(childNode, filename); + } + else if (xmlStrEqual(childNode->name, BAD_CAST "status-effect")) + { + // status effects config + StatusManager::readStatusNode(childNode, filename); + } + else + { + // since the client and server share settings, don't be too strict +// LOG_WARN("Unexpected tag <" << childNode->name << "> in " << filename); + } + } + + // remove this file from include stack + mIncludedFiles.erase(filename); +} + +/** + * Finalize the configuration loading and check if all managers are happy with it. + */ +void SettingsManager::checkStatus() +{ + attributeManager->checkStatus(); + skillManager->checkStatus(); + specialManager->checkStatus(); + itemManager->checkStatus(); + monsterManager->checkStatus(); + emoteManager->checkStatus(); + StatusManager::checkStatus(); +} diff --git a/src/game-server/settingsmanager.h b/src/game-server/settingsmanager.h new file mode 100644 index 0000000..aa6d272 --- /dev/null +++ b/src/game-server/settingsmanager.h @@ -0,0 +1,51 @@ +/* + * 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 GAMESERVER_SETTINGSMANAGER_H_ +#define GAMESERVER_SETTINGSMANAGER_H_ + +#include +#include +#include + +class SettingsManager +{ + public: + SettingsManager(const std::string &settingsFile): + mSettingsFile(settingsFile) + {} + + void initialize(); + + void reload(); + + private: + std::string mSettingsFile; + std::set mIncludedFiles; + + void loadFile(const std::string &filename); + + void checkStatus(); +}; + + +extern SettingsManager *settingsManager; + +#endif // GAMESERVER_SETTINGSMANAGER_H_ diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp index 69a875e..8ebe18f 100644 --- a/src/game-server/skillmanager.cpp +++ b/src/game-server/skillmanager.cpp @@ -34,44 +34,48 @@ void SkillManager::clear() mSkillsInfo.clear(); mNamedSkillsInfo.clear(); + mDefaultSkillId = 0; } void SkillManager::initialize() { clear(); +} - XML::Document doc(mSkillFile); - xmlNodePtr rootNode = doc.rootNode(); +void SkillManager::reload() +{ + initialize(); +} - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skills")) +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void SkillManager::readSkillSetNode(xmlNodePtr node, const std::string& filename) +{ + std::string setName = XML::getProperty(node, "name", std::string()); + if (setName.empty()) { - LOG_ERROR("Skill Manager: " << mSkillFile - << " is not a valid database file!"); + LOG_WARN("The " << filename << " file is containing unamed " + "tags and will be ignored."); return; } - LOG_INFO("Loading skill reference: " << mSkillFile); + setName = utils::toLower(setName); - for_each_xml_child_node(setNode, rootNode) + for_each_xml_child_node(skillNode, node) { - // The server will prefix the core name with the set, so we need one. - if (!xmlStrEqual(setNode->name, BAD_CAST "set")) - continue; - - std::string setName = XML::getProperty(setNode, "name", std::string()); - if (setName.empty()) - { - LOG_WARN("The " << mSkillFile << " file is containing unamed " - "tags and will be ignored."); - continue; - } - - setName = utils::toLower(setName); - - for_each_xml_child_node(skillNode, setNode) + if (xmlStrEqual(skillNode->name, BAD_CAST "skill")) { readSkillNode(skillNode, setName); + } } +} +/** + * Check the status of recently loaded configuration. + */ +void SkillManager::checkStatus() +{ printDebugSkillTable(); if (!mDefaultSkillId) @@ -79,8 +83,7 @@ void SkillManager::initialize() "Skill map loading. " "Players won't be able to earn XP when unarmed."); - LOG_INFO("Loaded " << mSkillsInfo.size() << " skills from " - << mSkillFile); + LOG_INFO("Loaded " << mSkillsInfo.size() << " skills"); } void SkillManager::readSkillNode(xmlNodePtr skillNode, @@ -141,7 +144,7 @@ void SkillManager::printDebugSkillTable() if (::utils::Logger::mVerbosity >= ::utils::Logger::Debug) { std::string lastSet; - LOG_DEBUG("Skill map in " << mSkillFile << ":" + LOG_DEBUG("Skill map:" << std::endl << "-----"); for (SkillsInfo::iterator it = mSkillsInfo.begin(); it != mSkillsInfo.end(); ++it) diff --git a/src/game-server/skillmanager.h b/src/game-server/skillmanager.h index 85f7f42..12828fe 100644 --- a/src/game-server/skillmanager.h +++ b/src/game-server/skillmanager.h @@ -28,8 +28,7 @@ class SkillManager { public: - SkillManager(const std::string & skillFile): - mSkillFile(skillFile), + SkillManager(): mDefaultSkillId(0) {} @@ -64,6 +63,11 @@ class SkillManager unsigned getDefaultSkillId() const { return mDefaultSkillId; } + + void readSkillSetNode(xmlNodePtr node, const std::string &filename); + + void checkStatus(); + private: struct SkillInfo { SkillInfo(): @@ -80,12 +84,9 @@ class SkillManager */ void clear(); - void readSkillNode(xmlNodePtr skillNode, const std::string& setName); - void printDebugSkillTable(); - // The skill file (skills.xml) - std::string mSkillFile; + void readSkillNode(xmlNodePtr skillNode, const std::string& setName); // The skill map typedef std::map SkillsInfo; diff --git a/src/game-server/specialmanager.cpp b/src/game-server/specialmanager.cpp index 39616fa..0840d25 100644 --- a/src/game-server/specialmanager.cpp +++ b/src/game-server/specialmanager.cpp @@ -36,6 +36,39 @@ static SpecialManager::TargetMode getTargetByString(const std::string &str) return SpecialManager::TARGET_BEING; } + +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void SpecialManager::readSpecialSetNode(xmlNodePtr node, const std::string &filename) +{ + std::string setName = XML::getProperty(node, "name", std::string()); + if (setName.empty()) + { + LOG_WARN("The " << filename << " file contains unamed tags and will be ignored."); + return; + } + + setName = utils::toLower(setName); + + for_each_xml_child_node(specialNode, node) + { + if (xmlStrEqual(specialNode->name, BAD_CAST "special")) { + readSpecialNode(specialNode, setName); + } + } + +} + +/** + * Check the status of recently loaded configuration. + */ +void SpecialManager::checkStatus() +{ + LOG_INFO("Loaded " << mSpecialsInfo.size() << " specials"); +} + void SpecialManager::readSpecialNode(xmlNodePtr specialNode, const std::string &setName) { @@ -94,42 +127,11 @@ void SpecialManager::readSpecialNode(xmlNodePtr specialNode, void SpecialManager::initialize() { clear(); +} - XML::Document doc(mSpecialFile); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "specials")) - { - LOG_ERROR("Special Manager: " << mSpecialFile - << " is not a valid database file!"); - return; - } - - LOG_INFO("Loading special reference: " << mSpecialFile); - - for_each_xml_child_node(setNode, rootNode) - { - // The server will prefix the core name with the set, so we need one. - if (!xmlStrEqual(setNode->name, BAD_CAST "set")) - continue; - - std::string setName = XML::getProperty(setNode, "name", std::string()); - if (setName.empty()) - { - LOG_WARN("The " << mSpecialFile << " file is containing unamed " - "tags and will be ignored."); - continue; - } - - setName = utils::toLower(setName); - - for_each_xml_child_node(specialNode, setNode) - { - if (!xmlStrEqual(specialNode->name, BAD_CAST "special")) - continue; - readSpecialNode(specialNode, setName); - } - } +void SpecialManager::reload() +{ + clear(); } void SpecialManager::clear() diff --git a/src/game-server/specialmanager.h b/src/game-server/specialmanager.h index e9203a3..b5ac874 100644 --- a/src/game-server/specialmanager.h +++ b/src/game-server/specialmanager.h @@ -59,8 +59,7 @@ public: Script::Ref useCallback; }; - SpecialManager(const std::string &specialFile): - mSpecialFile(specialFile) + SpecialManager() { } ~SpecialManager() @@ -92,6 +91,11 @@ public: SpecialInfo *getSpecialInfo(int id); + + void readSpecialSetNode(xmlNodePtr node, const std::string &filename); + + void checkStatus(); + private: /** * Clears up the special maps. @@ -101,7 +105,6 @@ private: void readSpecialNode(xmlNodePtr skillNode, const std::string &setName); - std::string mSpecialFile; typedef std::map SpecialsInfo; SpecialsInfo mSpecialsInfo; typedef utils::NameMap NamedSpecialsInfo; diff --git a/src/game-server/statusmanager.cpp b/src/game-server/statusmanager.cpp index 389c4cc..2056b58 100644 --- a/src/game-server/statusmanager.cpp +++ b/src/game-server/statusmanager.cpp @@ -32,74 +32,15 @@ typedef std::map< int, StatusEffect * > StatusEffectsMap; static StatusEffectsMap statusEffects; static utils::NameMap statusEffectsByName; -static std::string statusReferenceFile; -void StatusManager::initialize(const std::string &file) +void StatusManager::initialize() { - statusReferenceFile = file; - reload(); + } void StatusManager::reload() { - XML::Document doc(statusReferenceFile); - xmlNodePtr rootNode = doc.rootNode(); - - if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "status-effects")) - { - LOG_ERROR("Status Manager: Error while parsing status database (" - << statusReferenceFile << ")!"); - return; - } - - LOG_INFO("Loading status reference: " << statusReferenceFile); - for_each_xml_child_node(node, rootNode) - { - if (!xmlStrEqual(node->name, BAD_CAST "status-effect")) - continue; - - const int id = XML::getProperty(node, "id", 0); - if (id < 1) - { - LOG_WARN("Status Manager: The status ID: " << id << " in " - << statusReferenceFile - << " is invalid and will be ignored."); - continue; - } - - StatusEffect *statusEffect = new StatusEffect(id); - - const std::string name = XML::getProperty(node, "name", - std::string()); - if (!name.empty()) - { - if (statusEffectsByName.contains(name)) - { - LOG_WARN("StatusManager: name not unique for status effect " - << id); - } - else - { - statusEffectsByName.insert(name, statusEffect); - } - } - - //TODO: Get these modifiers -/* - modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_MIN, XML::getProperty(node, "attack-min", 0)); - modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_DELTA, XML::getProperty(node, "attack-delta", 0)); - modifiers.setAttributeValue(BASE_ATTR_HP, XML::getProperty(node, "hp", 0)); - modifiers.setAttributeValue(BASE_ATTR_PHY_RES, XML::getProperty(node, "defense", 0)); - modifiers.setAttributeValue(CHAR_ATTR_STRENGTH, XML::getProperty(node, "strength", 0)); - modifiers.setAttributeValue(CHAR_ATTR_AGILITY, XML::getProperty(node, "agility", 0)); - modifiers.setAttributeValue(CHAR_ATTR_DEXTERITY, XML::getProperty(node, "dexterity", 0)); - modifiers.setAttributeValue(CHAR_ATTR_VITALITY, XML::getProperty(node, "vitality", 0)); - modifiers.setAttributeValue(CHAR_ATTR_INTELLIGENCE, XML::getProperty(node, "intelligence", 0)); - modifiers.setAttributeValue(CHAR_ATTR_WILLPOWER, XML::getProperty(node, "willpower", 0)); -*/ - - statusEffects[id] = statusEffect; - } + deinitialize(); } void StatusManager::deinitialize() @@ -123,3 +64,62 @@ StatusEffect *StatusManager::getStatusByName(const std::string &name) { return statusEffectsByName.value(name); } + +/** + * Read a element from settings. + * Used by SettingsManager. + */ +void StatusManager::readStatusNode(xmlNodePtr node, const std::string &filename) +{ + const int id = XML::getProperty(node, "id", 0); + if (id < 1) + { + LOG_WARN("Status Manager: The status ID: " << id << " in " + << filename + << " is invalid and will be ignored."); + return; + } + + StatusEffect *statusEffect = new StatusEffect(id); + + const std::string name = XML::getProperty(node, "name", + std::string()); + if (!name.empty()) + { + if (statusEffectsByName.contains(name)) + { + LOG_WARN("StatusManager: name not unique for status effect " + << id); + } + else + { + statusEffectsByName.insert(name, statusEffect); + } + } + + //TODO: Get these modifiers +/* + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_MIN, XML::getProperty(node, "attack-min", 0)); + modifiers.setAttributeValue(BASE_ATTR_PHY_ATK_DELTA, XML::getProperty(node, "attack-delta", 0)); + modifiers.setAttributeValue(BASE_ATTR_HP, XML::getProperty(node, "hp", 0)); + modifiers.setAttributeValue(BASE_ATTR_PHY_RES, XML::getProperty(node, "defense", 0)); + modifiers.setAttributeValue(CHAR_ATTR_STRENGTH, XML::getProperty(node, "strength", 0)); + modifiers.setAttributeValue(CHAR_ATTR_AGILITY, XML::getProperty(node, "agility", 0)); + modifiers.setAttributeValue(CHAR_ATTR_DEXTERITY, XML::getProperty(node, "dexterity", 0)); + modifiers.setAttributeValue(CHAR_ATTR_VITALITY, XML::getProperty(node, "vitality", 0)); + modifiers.setAttributeValue(CHAR_ATTR_INTELLIGENCE, XML::getProperty(node, "intelligence", 0)); + modifiers.setAttributeValue(CHAR_ATTR_WILLPOWER, XML::getProperty(node, "willpower", 0)); +*/ + + statusEffects[id] = statusEffect; + +} + +/** + * Check the status of recently loaded configuration. + */ +void StatusManager::checkStatus() +{ + LOG_INFO("Loaded " << statusEffects.size() << " status effects"); +} + diff --git a/src/game-server/statusmanager.h b/src/game-server/statusmanager.h index 8ab321d..cd34138 100644 --- a/src/game-server/statusmanager.h +++ b/src/game-server/statusmanager.h @@ -22,6 +22,7 @@ #define STATUSMANAGER_H #include +#include "utils/xml.h" class StatusEffect; @@ -30,7 +31,7 @@ namespace StatusManager /** * Loads status reference file. */ - void initialize(const std::string &); + void initialize(); /** * Reloads status reference file. @@ -51,6 +52,10 @@ namespace StatusManager * Gets the status having the given name. */ StatusEffect *getStatusByName(const std::string &name); + + void readStatusNode(xmlNodePtr node, const std::string &filename); + + void checkStatus(); } #endif // STATUSMANAGER_H -- cgit