diff options
-rw-r--r-- | example/clientdata/equip.xml | 25 | ||||
-rw-r--r-- | src/game-server/inventory.cpp | 2 | ||||
-rw-r--r-- | src/game-server/itemmanager.cpp | 105 | ||||
-rw-r--r-- | src/game-server/itemmanager.h | 44 | ||||
-rw-r--r-- | src/game-server/state.cpp | 2 |
5 files changed, 99 insertions, 79 deletions
diff --git a/example/clientdata/equip.xml b/example/clientdata/equip.xml index 0d1c1d3b..097229cd 100644 --- a/example/clientdata/equip.xml +++ b/example/clientdata/equip.xml @@ -1,12 +1,19 @@ <?xml version="1.0" encoding="utf-8"?> +<!-- Notes: + The id and name parameters must be unique. + The count parameter indicates the 'size' of the slot. + The visible parameter indicates whether the item is visible + on the map character. Hence, whether the server should send appearance + updates when making changes on it. +--> <equip-slots> - <slot name="hand" count="2" visible="true" /> - <slot name="torso" count="1" visible="true" /> - <slot name="arms" count="1" /> - <slot name="head" count="1" visible="true" /> - <slot name="legs" count="1" visible="true" /> - <slot name="ring" count="1" /> - <slot name="necklace" count="1" /> - <slot name="feet" count="1" /> - <slot name="ammo" count="1" /> + <slot id="1" name="hand" capacity="2" visible="true" /> + <slot id="2" name="torso" capacity="1" visible="true" /> + <slot id="3" name="arms" capacity="1" /> + <slot id="4" name="head" capacity="1" visible="true" /> + <slot id="5" name="legs" capacity="1" visible="true" /> + <slot id="6" name="ring" capacity="1" /> + <slot id="7" name="necklace" capacity="1" /> + <slot id="8" name="feet" capacity="1" /> + <slot id="9" name="ammo" capacity="1" /> </equip-slots> diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 988877ca..44aac044 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -574,7 +574,7 @@ bool Inventory::equip(int slot, bool override) ++it3) { // it3 -> { slot id, number required } - unsigned int max = itemManager->getMaxSlotsFromId(it3->first), + unsigned int max = itemManager->getEquipSlotCapacity(it3->first), used = mPoss->equipSlots.count(it3->first); if (max - used >= it3->second) continue; diff --git a/src/game-server/itemmanager.cpp b/src/game-server/itemmanager.cpp index d21c791c..bfe34899 100644 --- a/src/game-server/itemmanager.cpp +++ b/src/game-server/itemmanager.cpp @@ -71,52 +71,22 @@ unsigned int ItemManager::getDatabaseVersion() const return mItemDatabaseVersion; } -const std::string &ItemManager::getEquipNameFromId(unsigned int id) const +unsigned int ItemManager::getEquipSlotIdFromName(const std::string &name) const { - return mEquipSlots.at(id).first; + EquipSlotInfo *slotInfo = mNamedEquipSlotsInfo.find(name); + return slotInfo ? slotInfo->slotId : 0; } -unsigned int ItemManager::getEquipIdFromName(const std::string &name) const +unsigned int ItemManager::getEquipSlotCapacity(unsigned int id) const { - for (unsigned int i = 0; i < mEquipSlots.size(); ++i) - if (name == mEquipSlots.at(i).first) - return i; - LOG_WARN("Item Manager: attempt to find equip id from name \"" << - name << "\" not found, defaulting to 0!"); - return 0; -} - -unsigned int ItemManager::getMaxSlotsFromId(unsigned int id) const -{ - return mEquipSlots.at(id).second; -} - -unsigned int ItemManager::getVisibleSlotCount() const -{ - if (!mVisibleEquipSlotCount) - { - for (VisibleEquipSlots::const_iterator it = mVisibleEquipSlots.begin(), - it_end = mVisibleEquipSlots.end(); - it != it_end; - ++it) - { - mVisibleEquipSlotCount += mEquipSlots.at(*it).second; - } - } - return mVisibleEquipSlotCount; + EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); + return i != mEquipSlotsInfo.end() ? i->second.slotCapacity : 0; } bool ItemManager::isEquipSlotVisible(unsigned int id) const { - for (VisibleEquipSlots::const_iterator it = mVisibleEquipSlots.begin(), - it_end = mVisibleEquipSlots.end(); - it != it_end; - ++it) - { - if (*it == id) - return true; - } - return false; + EquipSlotsInfo::const_iterator i = mEquipSlotsInfo.find(id); + return i != mEquipSlotsInfo.end() ? i->second.visibleSlot : false; } void ItemManager::readEquipSlotsFile() @@ -133,42 +103,55 @@ void ItemManager::readEquipSlotsFile() LOG_INFO("Loading equip slots: " << mEquipSlotsFile); - unsigned totalCount = 0; + unsigned totalCapacity = 0; unsigned slotCount = 0; - unsigned visibleSlotCount = 0; + mVisibleEquipSlotCount = 0; for_each_xml_child_node(node, rootNode) { 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 count = XML::getProperty(node, "count", 0); + const int capacity = XML::getProperty(node, "capacity", 0); - if (name.empty() || count <= 0) + if (slotId <= 0 || name.empty() || capacity <= 0) { - LOG_WARN("Item Manager: equip slot has no name or zero count"); + LOG_WARN("Item Manager: equip slot " << slotId + << ": (" << name << ") has no name or zero count. " + "The slot has been ignored."); + continue; } - else + + bool visible = XML::getBoolProperty(node, "visible", false); + if (visible) { - bool visible = XML::getProperty(node, "visible", "false") != "false"; - if (visible) + if (++mVisibleEquipSlotCount > 7) { - mVisibleEquipSlots.push_back(mEquipSlots.size()); - if (++visibleSlotCount > 7) - LOG_WARN("Item Manager: More than 7 visible equip slot!" - "This will not work with current netcode!"); + LOG_WARN("Item Manager: More than 7 visible equip slot!" + "This will not work with current netcode!"); } - mEquipSlots.push_back(std::pair<std::string, unsigned int> - (name, count)); - totalCount += count; - ++slotCount; } + + EquipSlotsInfo::iterator i = mEquipSlotsInfo.find(slotId); + + if (i != mEquipSlotsInfo.end()) + { + LOG_WARN("Item Manager: Ignoring duplicate definition " + "of equip slot '" << slotId << "'!"); + continue; + } + EquipSlotInfo equipSlotInfo(slotId, name, capacity, visible); + mEquipSlotsInfo[slotId] = equipSlotInfo; + mNamedEquipSlotsInfo.insert(name, &equipSlotInfo); + totalCapacity += capacity; + ++slotCount; } } LOG_INFO("Loaded '" << slotCount << "' slot types with '" - << totalCount << "' slots."); + << totalCapacity << "' slots."); } void ItemManager::readItemsFile() @@ -274,8 +257,18 @@ void ItemManager::readEquipNode(xmlNodePtr equipNode, ItemClass *item) LOG_WARN("Item Manager: empty equip slot definition!"); continue; } - req.push_back(std::make_pair(getEquipIdFromName(slot), + if (utils::isNumeric(slot)) + { + // When the slot id is given + req.push_back(std::make_pair(utils::stringToInt(slot), + XML::getProperty(subNode, "required", 1))); + } + else + { + // When its name is given + req.push_back(std::make_pair(getEquipSlotIdFromName(slot), XML::getProperty(subNode, "required", 1))); + } } } if (req.empty()) diff --git a/src/game-server/itemmanager.h b/src/game-server/itemmanager.h index c310df44..29feee87 100644 --- a/src/game-server/itemmanager.h +++ b/src/game-server/itemmanager.h @@ -30,6 +30,24 @@ class ItemClass; +struct EquipSlotInfo +{ + EquipSlotInfo(): + slotId(0), slotCapacity(0), visibleSlot(false) + {} + + EquipSlotInfo(unsigned int id, const std::string &name, + unsigned int capacity, bool visible): + slotId(id), slotName(name), slotCapacity(capacity), visibleSlot(visible) + {} + + unsigned int slotId; + std::string slotName; + unsigned int slotCapacity; + bool visibleSlot; +}; + + class ItemManager { public: @@ -73,13 +91,12 @@ class ItemManager */ unsigned int getDatabaseVersion() const; - const std::string &getEquipNameFromId(unsigned int id) const; - - unsigned int getEquipIdFromName(const std::string &name) const; + unsigned int getEquipSlotIdFromName(const std::string &name) const; - unsigned int getMaxSlotsFromId(unsigned int id) const; + unsigned int getEquipSlotCapacity(unsigned int id) const; - unsigned int getVisibleSlotCount() const; + unsigned int getVisibleEquipSlotCount() const + { return mVisibleEquipSlotCount; } bool isEquipSlotVisible(unsigned int id) const; @@ -94,19 +111,22 @@ class ItemManager void readEffectNode(xmlNodePtr effectNode, ItemClass *item); typedef std::map< int, ItemClass * > ItemClasses; - // Map a string (name of slot) with (str-id, max-per-equip-slot) - typedef std::vector< std::pair< std::string, unsigned int > > EquipSlots; + ItemClasses mItemClasses; /**< Item reference */ + utils::NameMap<ItemClass*> mItemClassesByName; + + // Map an equip slot id with the equip slot info. + typedef std::map< unsigned int, EquipSlotInfo > EquipSlotsInfo; // Reference to the vector position of equipSlots typedef std::vector< unsigned int > VisibleEquipSlots; - ItemClasses mItemClasses; /**< Item reference */ - utils::NameMap<ItemClass*> mItemClassesByName; - EquipSlots mEquipSlots; - VisibleEquipSlots mVisibleEquipSlots; + EquipSlotsInfo mEquipSlotsInfo; + // Map a string (name of slot) with (str-id, max-per-equip-slot) + // We only keep a pointer to it: The id map will take care of deletion. + utils::NameMap<EquipSlotInfo* > mNamedEquipSlotsInfo; std::string mItemsFile; std::string mEquipSlotsFile; - mutable unsigned int mVisibleEquipSlotCount; // Cache + unsigned int mVisibleEquipSlotCount; // Cache /** Version of the loaded items database file.*/ unsigned int mItemDatabaseVersion; diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp index 1a9c0204..d8f9b183 100644 --- a/src/game-server/state.cpp +++ b/src/game-server/state.cpp @@ -109,7 +109,7 @@ static void updateMap(MapComposite *map) static void serializeLooks(Character *ch, MessageOut &msg, bool full) { const EquipData &equipData = ch->getPossessions().getEquipment(); - unsigned int nb_slots = itemManager->getVisibleSlotCount(); + unsigned int nb_slots = itemManager->getVisibleEquipSlotCount(); // Bitmask describing the changed entries. int changed = (1 << nb_slots) - 1; |