From 89ad830bb1c0a290e9cd93d37de253db8f9a6eb5 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Tue, 30 Aug 2011 21:10:56 +0200 Subject: Avoid crashing the game server when the last argument is quoted. Resolves: Mana-Mantis #386 Reviewed-by: o11c. --- src/game-server/commandhandler.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp index f0cbcf3b..189da538 100644 --- a/src/game-server/commandhandler.cpp +++ b/src/game-server/commandhandler.cpp @@ -186,7 +186,15 @@ static std::string getArgument(std::string &args) // Jumps to the next parameter, // after the ending double-quote and space, // and remove the two double-quotes before returning. - args = args.substr(pos + 2); + if (pos + 2 < args.size()) + { + args = args.substr(pos + 2); + } + else + { + // This was the last argument + args.clear(); + } argument = argument.substr(1, pos - 1); } else -- cgit v1.2.3-70-g09d2 From bf04bd4cfe406ef8d2de5cd50dc0e9e7e91c6893 Mon Sep 17 00:00:00 2001 From: Erik Schilling Date: Wed, 31 Aug 2011 17:48:11 +0800 Subject: Added chatcommand to get position of a character. Add chatcommand @getpos which return the mapid and location of the character. Part of: Mana-Mantis: #385. Reviewed-by: Bertram. --- example/serverdata/permissions.xml | 1 + src/game-server/commandhandler.cpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'src') diff --git a/example/serverdata/permissions.xml b/example/serverdata/permissions.xml index c07bfae2..6ad941d6 100644 --- a/example/serverdata/permissions.xml +++ b/example/serverdata/permissions.xml @@ -22,6 +22,7 @@ @attribute @charwarp @killmonsters + @getpos gm diff --git a/src/game-server/commandhandler.cpp b/src/game-server/commandhandler.cpp index 189da538..0cde9891 100644 --- a/src/game-server/commandhandler.cpp +++ b/src/game-server/commandhandler.cpp @@ -76,6 +76,7 @@ static void handleLog(Character*, std::string&); static void handleLogsay(Character*, std::string&); static void handleKillMonsters(Character*, std::string&); static void handleCraft(Character*, std::string&); +static void handleGetPos(Character*, std::string&); static CmdRef const cmdRef[] = { @@ -133,6 +134,8 @@ static CmdRef const cmdRef[] = "Kills all monsters on the map.", &handleKillMonsters}, {"craft", "{ }", "Crafts something.", &handleCraft}, + {"getpos", "", + "Gets the position of a character.", &handleGetPos}, {NULL, NULL, NULL, NULL} }; @@ -1377,6 +1380,36 @@ static void handleCraft(Character *player, std::string &args) } } +static void handleGetPos(Character *player, std::string &args) +{ + std::string character = getArgument(args); + if (character.empty()) + { + say("Invalid amount of arguments given.", player); + say("Usage: @getpos ", player); + return; + } + Character *other; + other = getPlayer(character); + if (!other) + { + say("Invalid character, or they are offline.", player); + return; + } + const Point &pos = other->getPosition(); + std::stringstream str; + str << "The current location of " + << character + << " is map " + << other->getMapId() + << " [" + << pos.x + << ":" + << pos.y + << "]"; + say(str.str(), player); +} + void CommandHandler::handleCommand(Character *player, const std::string &command) { -- cgit v1.2.3-70-g09d2 From 04fb1b30a04b6d90abc1561c2d11c2371a29bc98 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 27 Jul 2011 12:36:04 +0200 Subject: Small random code format cleanups, and documentation fixes. This doesn't change anything yet. Reviewed-by: o11c. --- src/common/inventorydata.h | 2 +- src/game-server/character.cpp | 2 +- src/game-server/inventory.cpp | 85 ++++++++++++++++++++++--------------------- src/game-server/inventory.h | 38 ++----------------- src/game-server/item.h | 2 + 5 files changed, 50 insertions(+), 79 deletions(-) (limited to 'src') diff --git a/src/common/inventorydata.h b/src/common/inventorydata.h index 4c637cc3..9127c816 100644 --- a/src/common/inventorydata.h +++ b/src/common/inventorydata.h @@ -26,12 +26,12 @@ /** * Numbers of inventory slots + * TODO: Make this configurable and sent to the client. */ #define INVENTORY_SLOTS 50 /** * Structure storing an item in the inventory. - * When the itemId is zero, this item represents "amount" consecutive empty slots. */ struct InventoryItem { diff --git a/src/game-server/character.cpp b/src/game-server/character.cpp index bbe26bd6..ef001638 100644 --- a/src/game-server/character.cpp +++ b/src/game-server/character.cpp @@ -81,7 +81,7 @@ Character::Character(MessageIn &msg): setName(msg.readString()); deserializeCharacterData(*this, msg); mOld = getPosition(); - Inventory(this).initialise(); + Inventory(this).initialize(); modifiedAllAttribute(); setSize(16); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 99390651..d7baedf2 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -28,15 +28,9 @@ #include "net/messageout.h" #include "utils/logger.h" -// TODO: -// - Inventory::initialise() Usable but could use a few more things -// - Inventory::equip() Usable but last part would be nice - -typedef std::set ItemIdSet; - Inventory::Inventory(Character *p, bool d): mPoss(&p->getPossessions()), mInvMsg(GPMSG_INVENTORY), - mEqmMsg(GPMSG_EQUIP), mClient(p), mDelayed(d) + mEqmMsg(GPMSG_EQUIP), mCharacter(p), mDelayed(d) { } @@ -54,7 +48,7 @@ void Inventory::restart() void Inventory::cancel() { assert(mDelayed); - Possessions &poss = mClient->getPossessions(); + Possessions &poss = mCharacter->getPossessions(); if (mPoss != &poss) { delete mPoss; @@ -65,13 +59,13 @@ void Inventory::cancel() void Inventory::commit(bool doRestart) { - Possessions &poss = mClient->getPossessions(); + Possessions &poss = mCharacter->getPossessions(); /* Sends changes, whether delayed or not. */ if (mInvMsg.getLength() > 2) { /* Send the message to the client directly. Perhaps this should be done through an update flag, too? */ - gameHandler->sendTo(mClient, mInvMsg); + gameHandler->sendTo(mCharacter, mInvMsg); } if (mPoss != &poss) { @@ -79,11 +73,12 @@ void Inventory::commit(bool doRestart) { /* * Search for any and all changes to equipment. - * Search through equipment for changes between old and new equipment. + * Search through equipment for changes between + * old and new equipment. * Send changes directly when there is a change. - * Even when equipment references to invy slots are the same, it still - * needs to be searched for changes to the internal equiment slot - * usage. + * Even when equipment references to invy slots are the same, + * it still needs to be searched for changes + * to the internal equiment slot usage. * This is probably the worst part of doing this in delayed mode. */ IdSlotMap oldEquip, newEquip; @@ -170,7 +165,7 @@ void Inventory::commit(bool doRestart) that have just been sent to the client. */ if (mEqmMsg.getLength() > 2) - gameHandler->sendTo(mClient, mEqmMsg); + gameHandler->sendTo(mCharacter, mEqmMsg); if (doRestart) restart(); @@ -195,7 +190,7 @@ void Inventory::equip_sub(unsigned int newCount, IdSlotMap::const_iterator &it) ++count; } if (itemManager->isEquipSlotVisible(it->second)) - mClient->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); + mCharacter->raiseUpdateFlags(UPDATEFLAG_LOOKSCHANGE); } while ((++it)->first == invSlot); if (count) { @@ -212,7 +207,7 @@ void Inventory::prepare() if (!mDelayed) return; - Possessions *poss = &mClient->getPossessions(); + Possessions *poss = &mCharacter->getPossessions(); if (mPoss == poss) mPoss = new Possessions(*poss); } @@ -242,10 +237,10 @@ void Inventory::sendFull() const m.writeInt16(k->second); // inventory slot } - gameHandler->sendTo(mClient, m); + gameHandler->sendTo(mCharacter, m); } -void Inventory::initialise() +void Inventory::initialize() { assert(!mDelayed); @@ -256,6 +251,7 @@ void Inventory::initialise() * Remove unknown inventory items. */ + typedef std::set ItemIdSet; ItemIdSet itemIds; /* @@ -267,14 +263,14 @@ void Inventory::initialise() if (item) { if (itemIds.insert(it1->second.itemId).second) - item->useTrigger(mClient, ITT_IN_INVY); + item->useTrigger(mCharacter, ITT_IN_INVY); ++it1; } else { LOG_WARN("Inventory: deleting unknown item type " << it1->second.itemId << " from the inventory of '" - << mClient->getName() + << mCharacter->getName() << "'!"); mPoss->inventory.erase(it1++); } @@ -294,7 +290,8 @@ void Inventory::initialise() if (equipment.insert(it2->second).second) { /* - * Perform checks for equipped items - check that all needed slots are available. + * Perform checks for equipped items + * Check that all needed slots are available. */ // TODO - Not needed for testing everything else right now, but // will be needed for production @@ -302,16 +299,16 @@ void Inventory::initialise() * Apply all equip triggers. */ itemManager->getItem(mPoss->inventory.at(it2->second).itemId) - ->useTrigger(mClient, ITT_EQUIP); + ->useTrigger(mCharacter, ITT_EQUIP); } } equipment.clear(); - checkSize(); + checkInventorySize(); } -void Inventory::checkSize() +void Inventory::checkInventorySize() { /* * Check that the inventory size is greater than or equal to the size @@ -321,7 +318,7 @@ void Inventory::checkSize() * If not, forcibly delete (drop?) items from the end until it is. */ while (mPoss->inventory.size() > INVENTORY_SLOTS - || mClient->getModifiedAttribute(ATTR_INV_CAPACITY) < 0) + || mCharacter->getModifiedAttribute(ATTR_INV_CAPACITY) < 0) { LOG_WARN("Inventory: oversize inventory! Deleting '" << mPoss->inventory.rbegin()->second.amount @@ -330,7 +327,7 @@ void Inventory::checkSize() << "' from slot '" << mPoss->inventory.rbegin()->first << "' of character '" - << mClient->getName() + << mCharacter->getName() << "'!"); // FIXME Should probably be dropped rather than deleted. removeFromSlot(mPoss->inventory.rbegin()->first, @@ -400,7 +397,7 @@ unsigned int Inventory::insert(unsigned int itemId, unsigned int amount) if (it == it_end) break; } - checkSize(); + checkInventorySize(); return amount; } @@ -430,7 +427,8 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount, bool fo { if (eq) { - // If the item is equippable, we have additional checks to make. + // If the item is equippable, + // we have additional checks to make. bool ch = false; for (EquipData::iterator it2 = mPoss->equipSlots.begin(), it2_end = mPoss->equipSlots.end(); @@ -472,13 +470,14 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount, bool fo return 0; } if (force) - itemManager->getItem(itemId)->useTrigger(mClient, ITT_LEAVE_INVY); + itemManager->getItem(itemId)->useTrigger(mCharacter, ITT_LEAVE_INVY); // Rather inefficient, but still usable for now assuming small invy size. // FIXME return inv && !force ? remove(itemId, amount, true) : amount; } -unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, unsigned int amount) +unsigned int Inventory::move(unsigned int slot1, unsigned int slot2, + unsigned int amount) { if (!amount || slot1 == slot2 || slot2 >= INVENTORY_SLOTS) return amount; @@ -582,7 +581,7 @@ unsigned int Inventory::removeFromSlot(unsigned int slot, unsigned int amount) } if (!exists && it->second.itemId) { if (ItemClass *ic = itemManager->getItem(it->second.itemId)) - ic->useTrigger(mClient, ITT_LEAVE_INVY); + ic->useTrigger(mCharacter, ITT_LEAVE_INVY); } unsigned int sub = std::min(amount, it->second.amount); @@ -618,11 +617,11 @@ void Inventory::changeEquipment(ItemClass *oldI, ItemClass *newI) if (!oldI && !newI) return; if (oldI && newI) - oldI->useTrigger(mClient, ITT_EQUIPCHG); + oldI->useTrigger(mCharacter, ITT_EQUIPCHG); else if (oldI) - oldI->useTrigger(mClient, ITT_UNEQUIP); + oldI->useTrigger(mCharacter, ITT_UNEQUIP); else if (newI) - newI->useTrigger(mClient, ITT_EQUIP); + newI->useTrigger(mCharacter, ITT_EQUIP); } bool Inventory::equip(int slot, bool override) @@ -632,21 +631,21 @@ bool Inventory::equip(int slot, bool override) InventoryData::iterator it; if ((it = mPoss->inventory.find(slot)) == mPoss->inventory.end()) return false; - const ItemEquipsInfo &eq = itemManager->getItem(it->second.itemId)->getItemEquipData(); + const ItemEquipsInfo &eq = itemManager->getItem(it->second.itemId) + ->getItemEquipData(); if (eq.empty()) return false; ItemEquipInfo const *ovd = 0; // Iterate through all possible combinations of slots for (ItemEquipsInfo::const_iterator it2 = eq.begin(), - it2_end = eq.end(); - it2 != it2_end; - ++it2) + it2_end = eq.end(); it2 != it2_end; ++it2) { // Iterate through this combination of slots. /* * 0 = all ok, slots free * 1 = possible if other items are unequipped first - * 2 = impossible, requires too many slots even with other equipment being removed + * 2 = impossible, requires too many slots + * even with other equipment being removed */ int fail = 0; ItemEquipInfo::const_iterator it3, it3_end; @@ -736,10 +735,12 @@ bool Inventory::equip(int slot, bool override) if (ovd) { /* - * We did find an equip that works if we unequip other items, and we can override. + * We did find an equip that works if we unequip other items, + * and we can override. * Process unequip triggers for all items we have to unequip. * Process equip triggers for new item. - * Attempt to reequip any equipment we had to remove, but disallowing override. + * Attempt to reequip any equipment we had to remove, + * but disallowing override. */ // TODO - this would increase ease of use substatially, add as soon as diff --git a/src/game-server/inventory.h b/src/game-server/inventory.h index bd9da5c3..4a77ad93 100644 --- a/src/game-server/inventory.h +++ b/src/game-server/inventory.h @@ -24,37 +24,6 @@ #include "game-server/character.h" #include "net/messageout.h" -/*enum -{ -// Equipment rules: -// 1 torso equipment - EQUIP_TORSO_SLOT = 0, -// 1 arms equipment - EQUIP_ARMS_SLOT = 1, -// 1 head equipment - EQUIP_HEAD_SLOT = 2, -// 1 legs equipment - EQUIP_LEGS_SLOT = 3, -// 1 feet equipment - EQUIP_FEET_SLOT = 4, -// 2 rings - EQUIP_RING1_SLOT = 5, - EQUIP_RING2_SLOT = 6, -// 1 necklace - EQUIP_NECKLACE_SLOT = 7, -// Fight: -// 2 one-handed weapons -// or 1 two-handed weapon -// or 1 one-handed weapon + 1 shield. - EQUIP_FIGHT1_SLOT = 8, - EQUIP_FIGHT2_SLOT = 9, -// Projectile: -// this item does not amount to one, it only indicates the chosen projectile. - EQUIP_PROJECTILE_SLOT = 10, - - EQUIP_CLIENT_INVENTORY = 32 -};*/ - class ItemClass; /** @@ -100,7 +69,7 @@ class Inventory * Ensures the inventory is sane and apply equipment modifiers. * Should be run only once and the very first time. */ - void initialise(); + void initialize(); /** * Equips item from given inventory slot. @@ -178,7 +147,7 @@ class Inventory * Forcibly delete items from the end if it is not. * @todo Drop items instead? */ - void checkSize(); + void checkInventorySize(); /** * Helper function for equip() when computing changes to equipment @@ -202,9 +171,8 @@ class Inventory */ MessageOut mInvMsg; MessageOut mEqmMsg; /**< Update message containing equipment changes */ - Character *mClient; /**< Character to notify. */ + Character *mCharacter; /**< Character to notify. */ bool mDelayed; /**< Delayed changes. */ }; - #endif diff --git a/src/game-server/item.h b/src/game-server/item.h index 1c7639c5..dbcc278c 100644 --- a/src/game-server/item.h +++ b/src/game-server/item.h @@ -28,7 +28,9 @@ class Being; class Script; +// A pair indicating: Equipment slot id -> how much slots required. typedef std::list< std::pair< unsigned int, unsigned int> > ItemEquipInfo; +// The list of required slots to equip. typedef std::list< ItemEquipInfo > ItemEquipsInfo; /** -- cgit v1.2.3-70-g09d2 From 0228543e6602177d933f6c88de56601201a8ab76 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Fri, 26 Aug 2011 00:01:29 +0200 Subject: Fixed the trigger area declared within map files. The bug was pretty generic, as the contains() method of the Rectangle class wasn't checking against left and top sides according to the client view point. I also documented the call site. Resolves: Mana-Mantis #317. Reviewed-by: o11c. --- src/game-server/trigger.cpp | 6 +++++- src/utils/point.h | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp index f25b00b8..19ca3512 100644 --- a/src/game-server/trigger.cpp +++ b/src/game-server/trigger.cpp @@ -55,7 +55,11 @@ void TriggerArea::update() //skip garbage if (!(*i) || (*i)->getPublicID() == 0) continue; - if (mZone.contains((*i)->getPosition())) //<-- Why is this additional condition necessary? Shouldn't getInsideRectangleIterator already exclude those outside of the zone? --Crush + // The BeingIterator returns the mapZones in touch with the rectangle + // area. On the other hand, the beings contained in the map zones + // may not be within the rectangle area. Hence, this additional + // contains() condition. + if (mZone.contains((*i)->getPosition())) { insideNow.insert(*i); diff --git a/src/utils/point.h b/src/utils/point.h index 4402aa09..988b6c5a 100644 --- a/src/utils/point.h +++ b/src/utils/point.h @@ -75,8 +75,8 @@ class Rectangle bool contains(const Point &p) const { - return (p.x - x) < w && - (p.y - y) < h; + return (p.x >= x && p.x < x + w && + p.y >= y && p.y < y + h); } bool intersects(const Rectangle &r) const -- cgit v1.2.3-70-g09d2 From 602e448c1223a47853522bcd2ef78dc7c25d2b4e Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Fri, 26 Aug 2011 00:09:18 +0200 Subject: Made the npc_create() function use insertion enqueueing. As the server was exitting when the insertion was failing anyway, and because the GameState::update() doesn't allow actor insertion while the update process, it was then pretty weird to not use an enqueued insertion for it. Plus, it fixes an assertion failure when scheduling an npc creation. Resolves: Mana-Mantis #360. Reviewed-by: o11c. --- src/scripting/lua.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/scripting/lua.cpp b/src/scripting/lua.cpp index 546f4a66..7213bd09 100644 --- a/src/scripting/lua.cpp +++ b/src/scripting/lua.cpp @@ -206,10 +206,7 @@ static int npc_create(lua_State *s) } q->setMap(m); q->setPosition(Point(x, y)); - bool b = GameState::insert(q); - /* Do not try to deal with a failure there. There are some serious issues - if an insertion failed on an almost empty map. */ - assert(b); (void)b; + GameState::enqueueInsert(q); lua_pushlightuserdata(s, q); return 1; } -- cgit v1.2.3-70-g09d2 From 5b329318218fd2269b16b5908421f399a73b6298 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 28 Sep 2011 16:25:42 +0200 Subject: Turned the skill manager into a class. Ack-by: o11c. --- src/game-server/main-game.cpp | 4 +++- src/game-server/skillmanager.cpp | 5 ++--- src/game-server/skillmanager.h | 22 +++++++++++++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 0b786555..35b809e1 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -88,6 +88,7 @@ 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); /** Core game message handler */ GameHandler *gameHandler; @@ -193,7 +194,7 @@ static void initializeServer() exit(EXIT_MAP_FILE_NOT_FOUND); } attributeManager->initialize(); - SkillManager::initialize(DEFAULT_SKILLSDB_FILE); + skillManager->initialize(); itemManager->initialize(); monsterManager->initialize(); StatusManager::initialize(DEFAULT_STATUSDB_FILE); @@ -249,6 +250,7 @@ static void deinitializeServer() // Destroy Managers delete stringFilter; monsterManager->deinitialize(); + delete skillManager; skillManager = 0; itemManager->deinitialize(); MapManager::deinitialize(); StatusManager::deinitialize(); diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp index 75f5f53c..edd78c46 100644 --- a/src/game-server/skillmanager.cpp +++ b/src/game-server/skillmanager.cpp @@ -31,9 +31,8 @@ static SkillMap skillMap; static std::string skillReferenceFile; static std::string defaultSkillKey = std::string(); -void SkillManager::initialize(const std::string &file) +void SkillManager::initialize() { - skillReferenceFile = file; reload(); } @@ -44,7 +43,7 @@ void SkillManager::reload() skillMap["KNIFE"] = 101; */ - XML::Document doc(skillReferenceFile); + XML::Document doc(mSkillFile); xmlNodePtr rootNode = doc.rootNode(); if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skills")) diff --git a/src/game-server/skillmanager.h b/src/game-server/skillmanager.h index c6a73a5c..e0ea8276 100644 --- a/src/game-server/skillmanager.h +++ b/src/game-server/skillmanager.h @@ -24,12 +24,21 @@ #include -namespace SkillManager +class SkillManager { + public: + SkillManager(const std::string & skillFile): + mSkillFile(skillFile), + mDefaultSkillId(0) + {} + + ~SkillManager() + {} + /** * Loads skill reference file. */ - void initialize(const std::string &); + void initialize(); /** * Reloads skill reference file. @@ -41,7 +50,14 @@ namespace SkillManager * (not case-sensitive to reduce wall-bashing) */ int getIdFromString(const std::string &name); -} + + private: + // The skill file (skills.xml) + std::string mSkillFile; + + // The default skill id + unsigned int mDefaultSkillId; +}; -- cgit v1.2.3-70-g09d2 From 7ddeb3c927b81474548bbc13ebcd00eb5688c51a Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 28 Sep 2011 16:35:55 +0200 Subject: Rewrote the skill manager the same way as the item manager. This will permit better handling of both skills names and id. This is needed to start reworking on the auto-attack system. --- src/game-server/skillmanager.cpp | 238 +++++++++++++++++++-------------------- src/game-server/skillmanager.h | 39 +++++-- 2 files changed, 149 insertions(+), 128 deletions(-) (limited to 'src') diff --git a/src/game-server/skillmanager.cpp b/src/game-server/skillmanager.cpp index edd78c46..be6eef4b 100644 --- a/src/game-server/skillmanager.cpp +++ b/src/game-server/skillmanager.cpp @@ -20,173 +20,169 @@ #include "game-server/skillmanager.h" -#include "utils/string.h" // for the toUpper function #include "utils/logger.h" -#include "utils/xml.h" #include -typedef std::map< std::string, int > SkillMap; -static SkillMap skillMap; -static std::string skillReferenceFile; -static std::string defaultSkillKey = std::string(); - -void SkillManager::initialize() +void SkillManager::clear() { - reload(); + for (SkillsInfo::iterator it = mSkillsInfo.begin(), + it_end = mSkillsInfo.end(); it != it_end; ++it) + { + delete it->second; + } + + mSkillsInfo.clear(); + mNamedSkillsInfo.clear(); } -void SkillManager::reload() +void SkillManager::initialize() { - /* - skillMap["UNARMED"] = 100; - skillMap["KNIFE"] = 101; - */ + clear(); XML::Document doc(mSkillFile); xmlNodePtr rootNode = doc.rootNode(); if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "skills")) { - LOG_ERROR("Skill Manager: " << skillReferenceFile + LOG_ERROR("Skill Manager: " << mSkillFile << " is not a valid database file!"); return; } - LOG_INFO("Loading skill reference: " << skillReferenceFile); + LOG_INFO("Loading skill reference: " << mSkillFile); - for_each_xml_child_node(setnode, rootNode) + for_each_xml_child_node(setNode, rootNode) { - if (!xmlStrEqual(setnode->name, BAD_CAST "set")) + // The server will prefix the core name with the set, so we need one. + if (!xmlStrEqual(setNode->name, BAD_CAST "set")) continue; - // we don't care about sets server-sided (yet?) - for_each_xml_child_node(skillnode, setnode) + std::string setName = XML::getProperty(setNode, "name", std::string()); + if (setName.empty()) { - if (xmlStrEqual(skillnode->name, BAD_CAST "skill")) - { - std::string name = XML::getProperty(skillnode, "name", - std::string()); - name = utils::toUpper(name); - int id = XML::getProperty(skillnode, "id", 0); - if (id > 0 && !name.empty()) - { - bool duplicateKey = false; - for (SkillMap::iterator i = skillMap.begin(); - i != skillMap.end(); i++) - { - if (id == i->second) - { - LOG_ERROR("SkillManager: The same id: " << id - << " is given for skill names: " << i->first - << " and " << name); - LOG_ERROR("The skill reference: " << "'" << name - << "': " << id << " will be ignored."); - - duplicateKey = true; - break; - } - } - - if (!duplicateKey) - { - if (XML::getBoolProperty(skillnode, "default", false)) - { - if (!defaultSkillKey.empty()) - { - LOG_WARN("SkillManager: " - "Default Skill Key already defined as " - << defaultSkillKey - << ". Redefinit it as: " << name); - } - else - { - LOG_INFO("SkillManager: Defining " << name - << " as default weapon-type key."); - } - defaultSkillKey = name; - } - skillMap[name] = id; - } - } - } + 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) + readSkillNode(skillNode, setName); } - if (::utils::Logger::mVerbosity >= ::utils::Logger::Debug) + printDebugSkillTable(); + + if (!mDefaultSkillId) + LOG_WARN("SkillManager: No default weapon-type id was given during " + "Skill map loading. " + "Players won't be able to earn XP when unarmed."); + + LOG_INFO("Loaded " << mSkillsInfo.size() << " skills from " + << mSkillFile); +} + +void SkillManager::readSkillNode(xmlNodePtr skillNode, + const std::string& setName) +{ + if (!xmlStrEqual(skillNode->name, BAD_CAST "skill")) + return; + + SkillInfo *skillInfo = new SkillInfo; + skillInfo->setName = setName; + skillInfo->skillName = utils::toLower( + XML::getProperty(skillNode, "name", std::string())); + int id = XML::getProperty(skillNode, "id", 0); + + if (id <= 0 || skillInfo->skillName.empty()) { - LOG_DEBUG("Skill map in " << skillReferenceFile << ":" - << std::endl << "-----"); - for (SkillMap::iterator i = skillMap.begin(); i != skillMap.end(); i++) + LOG_WARN("Invalid skill (empty name or id <= 0) in set: " << setName); + return; + } + skillInfo->id = (unsigned)id; + + SkillsInfo::iterator it = mSkillsInfo.find(skillInfo->id); + if (it != mSkillsInfo.end()) + { + LOG_WARN("SkillManager: The same id: " << skillInfo->id + << " is given for skill names: " << it->first + << " and " << skillInfo->skillName); + LOG_WARN("The skill reference: " << skillInfo->id + << ": '" << skillInfo->skillName << "' will be ignored."); + return; + } + + if (XML::getBoolProperty(skillNode, "default", false)) + { + if (mDefaultSkillId) { - if (!defaultSkillKey.compare(i->first)) - { - LOG_DEBUG("'" << i->first << "': " << i->second - << " (Default)"); - } - else - { - LOG_DEBUG("'" << i->first << "': " << i->second); - } + LOG_WARN("SkillManager: " + "Default Skill id already defined as " + << mDefaultSkillId + << ". Redefinit it as: " << skillInfo->id); } - LOG_DEBUG("-----"); + else + { + LOG_INFO("SkillManager: Defining skill id: " << skillInfo->id + << " as default weapon-type id."); + } + mDefaultSkillId = skillInfo->id; } - if (defaultSkillKey.empty()) - LOG_WARN("SkillManager: No default weapon-type id was given during " - "Skill map loading. Defaults will fall back to id 0."); + mSkillsInfo.insert( + std::make_pair(skillInfo->id, skillInfo)); - LOG_INFO("Loaded " << skillMap.size() << " skill references from " - << skillReferenceFile); + std::string keyName = setName + "_" + skillInfo->skillName; + mNamedSkillsInfo.insert(keyName, skillInfo); } -int SkillManager::getIdFromString(const std::string &name) +void SkillManager::printDebugSkillTable() { - // Check if the name is an integer value. - if (utils::isNumeric(name)) + if (::utils::Logger::mVerbosity >= ::utils::Logger::Debug) { - int val = 0; - val = utils::stringToInt(name); - if (val) + std::string lastSet; + LOG_DEBUG("Skill map in " << mSkillFile << ":" + << std::endl << "-----"); + for (SkillsInfo::iterator it = mSkillsInfo.begin(); + it != mSkillsInfo.end(); ++it) { - for (SkillMap::iterator i = skillMap.begin(); i != skillMap.end(); i++) + if (!lastSet.compare(it->second->setName)) { - if (i->second == val) - return val; + lastSet = it->second->setName; + LOG_DEBUG("Skill set: " << lastSet); } - LOG_WARN("SkillManager::getIdFromString(): Numeric weapon-type id " - << val << " not found into " << skillReferenceFile); - SkillMap::iterator i = skillMap.find(defaultSkillKey); - if (i != skillMap.end()) + if (it->first == mDefaultSkillId) { - LOG_WARN("Id defaulted to " << defaultSkillKey << ": " - << i->second); - return i->second; + LOG_DEBUG("'" << it->first << "': " << it->second->skillName + << " (Default)"); } else { - LOG_WARN("Id defaulted to 0."); - return 0; + LOG_DEBUG("'" << it->first << "': " << it->second->skillName); } } - else - { - LOG_WARN("SkillManager: Invalid skill id " << name); - return 0; - } + LOG_DEBUG("-----"); } +} - // Convert to upper case for easier finding - SkillMap::iterator i = skillMap.find(utils::toUpper(name)); - if (i == skillMap.end()) - { - LOG_WARN("SkillManager: No weapon-type name corresponding to " - << utils::toUpper(name) << " into " << skillReferenceFile); - return 0; - } - else - { - return i->second; - } +unsigned int SkillManager::getId(const std::string& set, + const std::string &name) const +{ + std::string key = utils::toLower(set) + "_" + utils::toLower(name); + SkillInfo *skillInfo = mNamedSkillsInfo.find(key); + return skillInfo ? skillInfo->id : 0; +} + +const std::string SkillManager::getSkillName(unsigned int id) const +{ + SkillsInfo::const_iterator it = mSkillsInfo.find(id); + return it != mSkillsInfo.end() ? it->second->skillName : ""; +} + +const std::string SkillManager::getSetName(unsigned int id) const +{ + SkillsInfo::const_iterator it = mSkillsInfo.find(id); + return it != mSkillsInfo.end() ? it->second->setName : ""; } diff --git a/src/game-server/skillmanager.h b/src/game-server/skillmanager.h index e0ea8276..1912e2fc 100644 --- a/src/game-server/skillmanager.h +++ b/src/game-server/skillmanager.h @@ -22,7 +22,8 @@ #ifndef SKILLMANAGER_H #define SKILLMANAGER_H -#include +#include "utils/string.h" +#include "utils/xml.h" class SkillManager { @@ -33,7 +34,7 @@ class SkillManager {} ~SkillManager() - {} + { clear(); } /** * Loads skill reference file. @@ -46,19 +47,43 @@ class SkillManager void reload(); /** - * Gets the skill ID of a skill string - * (not case-sensitive to reduce wall-bashing) + * Gets the skill Id from a set and a skill string. */ - int getIdFromString(const std::string &name); + unsigned int getId(const std::string& set, const std::string &name) const; + const std::string getSkillName(unsigned int id) const; + const std::string getSetName(unsigned int id) const; private: + struct SkillInfo { + SkillInfo(): + id(0) + {} + + unsigned int id; + std::string setName; + std::string skillName; + }; + + /* + * Clears up the skill maps. + */ + void clear(); + + void readSkillNode(xmlNodePtr skillNode, const std::string& setName); + + void printDebugSkillTable(); + // The skill file (skills.xml) std::string mSkillFile; + // The skill map + typedef std::map SkillsInfo; + SkillsInfo mSkillsInfo; + // A map used to get skills per name. + utils::NameMap mNamedSkillsInfo; + // The default skill id unsigned int mDefaultSkillId; }; - - #endif // SKILLMANAGER_H -- cgit v1.2.3-70-g09d2 From da782617397773fb2f29a4021fe73a80e38f62dd Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Fri, 26 Aug 2011 06:18:31 +0800 Subject: Added a bit more precision on the conditions used in the TriggerArea::update() function. --- src/game-server/actor.h | 3 +++ src/game-server/trigger.cpp | 5 +++-- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/game-server/actor.h b/src/game-server/actor.h index 529d48c4..abc1e1d0 100644 --- a/src/game-server/actor.h +++ b/src/game-server/actor.h @@ -111,6 +111,9 @@ class Actor : public Thing void setPublicID(int id) { mPublicID = id; } + bool isPublicIdValid() const + { return (mPublicID > 0 && mPublicID != 65535); } + /** * Gets the way the actor blocks pathfinding for other actors. */ diff --git a/src/game-server/trigger.cpp b/src/game-server/trigger.cpp index 19ca3512..c4cec2f4 100644 --- a/src/game-server/trigger.cpp +++ b/src/game-server/trigger.cpp @@ -52,8 +52,9 @@ void TriggerArea::update() std::set insideNow; for (BeingIterator i(getMap()->getInsideRectangleIterator(mZone)); i; ++i) { - //skip garbage - if (!(*i) || (*i)->getPublicID() == 0) continue; + // Don't deal with unitialized actors. + if (!(*i) || !(*i)->isPublicIdValid()) + continue; // The BeingIterator returns the mapZones in touch with the rectangle // area. On the other hand, the beings contained in the map zones -- cgit v1.2.3-70-g09d2 From 3a72ea3a61b812924be76e2a0bccd2882a8b06ce Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Fri, 26 Aug 2011 01:12:25 +0200 Subject: Fixed mem leak on the item and monster manager unloading process Reviewed-by: o11c. Note: the initialize/reload() api problem will be fixed in another commit. --- src/game-server/itemmanager.h | 3 +++ src/game-server/main-game.cpp | 14 +++++++------- src/game-server/monstermanager.h | 7 ++++++- 3 files changed, 16 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/game-server/itemmanager.h b/src/game-server/itemmanager.h index c310df44..efd31710 100644 --- a/src/game-server/itemmanager.h +++ b/src/game-server/itemmanager.h @@ -40,6 +40,9 @@ class ItemManager mItemDatabaseVersion(0) {} + ~ItemManager() + { deinitialize(); } + /** * Loads item reference file. */ diff --git a/src/game-server/main-game.cpp b/src/game-server/main-game.cpp index 35b809e1..9d96a6ab 100644 --- a/src/game-server/main-game.cpp +++ b/src/game-server/main-game.cpp @@ -242,16 +242,16 @@ static void deinitializeServer() enet_deinitialize(); // Destroy message handlers - delete gameHandler; - delete accountHandler; - delete postMan; - delete gBandwidth; + delete gameHandler; gameHandler = 0; + delete accountHandler; accountHandler = 0; + delete postMan; postMan = 0; + delete gBandwidth; gBandwidth = 0; // Destroy Managers - delete stringFilter; - monsterManager->deinitialize(); + delete stringFilter; stringFilter = 0; + delete monsterManager; monsterManager = 0; delete skillManager; skillManager = 0; - itemManager->deinitialize(); + delete itemManager; itemManager = 0; MapManager::deinitialize(); StatusManager::deinitialize(); diff --git a/src/game-server/monstermanager.h b/src/game-server/monstermanager.h index f04a5733..07ebb58f 100644 --- a/src/game-server/monstermanager.h +++ b/src/game-server/monstermanager.h @@ -30,8 +30,13 @@ class MonsterClass; class MonsterManager { public: + MonsterManager(const std::string &file): + mMonsterReferenceFile(file) + {} + + ~MonsterManager() + { deinitialize(); } - MonsterManager(const std::string &file) : mMonsterReferenceFile(file) {} /** * Loads monster reference file. */ -- cgit v1.2.3-70-g09d2 From 3e218fec3000ab36ce03a0e3a04756bff9484127 Mon Sep 17 00:00:00 2001 From: Yohann Ferreira Date: Wed, 28 Sep 2011 16:57:36 +0200 Subject: Clarified the role of initialize() and reload() functions in the monster and item managers. ack-by: o11c. note: The managers still need to auto deinit when already loaded. This will be done in another trivial commit. --- src/game-server/itemmanager.cpp | 7 ++++--- src/game-server/monstermanager.cpp | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index d21c791c..9d94c389 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -32,12 +32,13 @@ #include #include -void ItemManager::initialize() +void ItemManager::reload() { - reload(); + deinitialize(); + initialize(); } -void ItemManager::reload() +void ItemManager::initialize() { mVisibleEquipSlotCount = 0; readEquipSlotsFile(); diff --git a/src/game-server/monstermanager.cpp b/src/game-server/monstermanager.cpp index 581dfd04..b7efd003 100644 --- a/src/game-server/monstermanager.cpp +++ b/src/game-server/monstermanager.cpp @@ -52,12 +52,13 @@ Element elementFromString (const std::string &name) return val == table.end() ? ELEMENT_ILLEGAL : (*val).second; } -void MonsterManager::initialize() +void MonsterManager::reload() { - reload(); + deinitialize(); + initialize(); } -void MonsterManager::reload() +void MonsterManager::initialize() { XML::Document doc(mMonsterReferenceFile); xmlNodePtr rootNode = doc.rootNode(); -- cgit v1.2.3-70-g09d2