diff options
Diffstat (limited to 'src/net/manaserv/inventoryhandler.cpp')
-rw-r--r-- | src/net/manaserv/inventoryhandler.cpp | 331 |
1 files changed, 244 insertions, 87 deletions
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp index 76fca7ae..c8dae1c3 100644 --- a/src/net/manaserv/inventoryhandler.cpp +++ b/src/net/manaserv/inventoryhandler.cpp @@ -26,33 +26,155 @@ #include "item.h" #include "itemshortcut.h" #include "localplayer.h" +#include "log.h" +#include "playerinfo.h" -#include "gui/chat.h" +#include "gui/inventorywindow.h" #include "net/manaserv/connection.h" #include "net/manaserv/messagein.h" #include "net/manaserv/messageout.h" -#include "net/manaserv/protocol.h" +#include "net/manaserv/manaserv_protocol.h" #include "resources/iteminfo.h" -#include "log.h" // <<< REMOVE ME! - extern Net::InventoryHandler *inventoryHandler; namespace ManaServ { extern Connection *gameServerConnection; +EquipBackend::EquipBackend() +{ + listen(Event::ClientChannel); +} + +Item *EquipBackend::getEquipment(int index) const +{ + if (index < 0 || (unsigned) index >= mSlots.size()) + return 0; + return mSlots.at(index); +} + +void EquipBackend::clear() +{ + for (std::vector<Item*>::iterator i = mSlots.begin(), i_end = mSlots.end(); + i != i_end; ++i) + { + if (Item *item = *i) + item->setEquipped(false); + } + mSlots.assign(mSlots.size(), 0); +} + +void EquipBackend::equip(int inventorySlot, int equipSlot, int amountUsed) +{ + if (equipSlot < 0 || (unsigned) equipSlot >= mSlotTypes.size()) + { + logger->log("ManaServ::EquipBackend: Equipment slot out of range"); + return; + } + + const SlotType &slotType = mSlotTypes.at(equipSlot); + Item *item = PlayerInfo::getInventory()->getItem(inventorySlot); + + if (!item) + { + logger->log("ManaServ::EquipBackend: No item at index %d", + inventorySlot); + return; + } + + // Start at first index and search upwards for free slots to place the + // item at the given inventory slot in + int i = slotType.firstIndex; + const int end_i = i + slotType.count; + + for (; i < end_i && amountUsed > 0; ++i) + { + if (!mSlots.at(i)) + { + mSlots[i] = item; + --amountUsed; + + item->setEquipped(true); + inventoryWindow->updateButtons(); + } + } +} + +void EquipBackend::unequip(int inventorySlot) +{ + Item *item = PlayerInfo::getInventory()->getItem(inventorySlot); + + if (!item) + { + logger->log("ManaServ::EquipBackend: No item at index %d", + inventorySlot); + return; + } + + for (unsigned i = 0; i < mSlots.size(); ++i) + if (mSlots.at(i) == item) + mSlots[i] = 0; + + item->setEquipped(false); + inventoryWindow->updateButtons(); +} + +void EquipBackend::event(Event::Channel, const Event &event) +{ + if (event.getType() == Event::LoadingDatabases) + readEquipFile(); +} + +void EquipBackend::readEquipFile() +{ + mSlots.clear(); + mSlotTypes.clear(); + + XML::Document doc("equip.xml"); + xmlNodePtr rootNode = doc.rootNode(); + + if (!rootNode || !xmlStrEqual(rootNode->name, BAD_CAST "equip-slots")) + { + logger->log("ManaServ::EquipBackend: Error while reading equip.xml!"); + return; + } + + int slotCount = 0; + + for_each_xml_child_node(childNode, rootNode) + { + if (!xmlStrEqual(childNode->name, BAD_CAST "slot")) + continue; + + SlotType slotType; + slotType.name = XML::getProperty(childNode, "name", std::string()); + slotType.count = XML::getProperty(childNode, "count", 1); + slotType.visible = XML::getBoolProperty(childNode, "visible", false); + slotType.firstIndex = slotCount; + + mSlotTypes.push_back(slotType); + slotCount += slotType.count; + } + + mSlots.resize(slotCount); +} + + InventoryHandler::InventoryHandler() { static const Uint16 _messages[] = { GPMSG_INVENTORY_FULL, GPMSG_INVENTORY, + GPMSG_EQUIP, 0 }; handledMessages = _messages; inventoryHandler = this; + + listen(Event::ItemChannel); } void InventoryHandler::handleMessage(Net::MessageIn &msg) @@ -60,114 +182,149 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg) switch (msg.getId()) { case GPMSG_INVENTORY_FULL: - player_node->clearInventory(); - player_node->mEquipment->setBackend(&mEquips); - // no break! - - case GPMSG_INVENTORY: - while (msg.getUnreadLength()) { - unsigned int slot = msg.readInt8(); - if (slot == 255) + PlayerInfo::clearInventory(); + PlayerInfo::getEquipment()->setBackend(&mEquipBackend); + int count = msg.readInt16(); + while (count--) { - player_node->setMoney(msg.readInt32()); - continue; + int slot = msg.readInt16(); + int id = msg.readInt16(); + int amount = msg.readInt16(); + PlayerInfo::setInventoryItem(slot, id, amount); } + while (msg.getUnreadLength()) + { + int equipSlot = msg.readInt8(); + int inventorySlot = msg.readInt16(); + mEquipBackend.equip(inventorySlot, equipSlot); + } + } + break; + + case GPMSG_INVENTORY: + while (msg.getUnreadLength()) + { + unsigned int slot = msg.readInt16(); int id = msg.readInt16(); - if (slot < EQUIPMENT_SIZE) + unsigned int amount = id ? msg.readInt16() : 0; + PlayerInfo::setInventoryItem(slot, id, amount); + } + break; + + case GPMSG_EQUIP: + while (msg.getUnreadLength()) + { + int inventorySlot = msg.readInt16(); + int equipSlotCount = msg.readInt8(); + + if (equipSlotCount == 0) { - mEquips.setEquipment(slot, id); + // No slots means to unequip this item + mEquipBackend.unequip(inventorySlot); } - else if (slot >= 32 && slot < 32 + getSize(Inventory::INVENTORY)) + else { - int amount = id ? msg.readInt8() : 0; - player_node->setInvItem(slot - 32, id, amount); + // Otherwise equip the item in the given slots + while (equipSlotCount--) + { + unsigned int equipSlot = msg.readInt8(); + unsigned int amountUsed = msg.readInt8(); + + mEquipBackend.equip(inventorySlot, equipSlot, + amountUsed); + } } - }; + } break; } } -void InventoryHandler::equipItem(const Item *item) -{ - MessageOut msg(PGMSG_EQUIP); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); -} - -void InventoryHandler::unequipItem(const Item *item) +void InventoryHandler::event(Event::Channel channel, + const Event &event) { - MessageOut msg(PGMSG_UNEQUIP); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); - - // Tidy equipment directly to avoid weapon still shown bug, for instance - int equipSlot = item->getInvIndex(); - logger->log("Unequipping %d", equipSlot); - mEquips.setEquipment(equipSlot, 0); -} + if (channel == Event::ItemChannel) + { + Item *item = event.getItem("item"); -void InventoryHandler::useItem(const Item *item) -{ - MessageOut msg(PGMSG_USE_ITEM); - msg.writeInt8(item->getInvIndex()); - gameServerConnection->send(msg); -} + if (!item) + return; -void InventoryHandler::dropItem(const Item *item, int amount) -{ - MessageOut msg(PGMSG_DROP); - msg.writeInt8(item->getInvIndex()); - msg.writeInt8(amount); - gameServerConnection->send(msg); -} + int index = item->getInvIndex(); -bool InventoryHandler::canSplit(const Item *item) -{ - return item && !item->isEquipment() && item->getQuantity() > 1; -} + if (event.getType() == Event::DoEquip) + { + MessageOut msg(PGMSG_EQUIP); + msg.writeInt8(index); + gameServerConnection->send(msg); + } + else if (event.getType() == Event::DoUnequip) + { + MessageOut msg(PGMSG_UNEQUIP); + msg.writeInt8(index); + gameServerConnection->send(msg); + } + else if (event.getType() == Event::DoUse) + { + MessageOut msg(PGMSG_USE_ITEM); + msg.writeInt8(index); + gameServerConnection->send(msg); + } + else if (event.getType() == Event::DoDrop) + { + int amount = event.getInt("amount", 1); -void InventoryHandler::splitItem(const Item *item, int amount) -{ - int newIndex = player_node->getInventory()->getFreeSlot(); - if (newIndex > Inventory::NO_SLOT_INDEX) - { - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt8(item->getInvIndex()); - msg.writeInt8(newIndex); - msg.writeInt8(amount); - gameServerConnection->send(msg); - } -} + MessageOut msg(PGMSG_DROP); + msg.writeInt8(index); + msg.writeInt8(amount); + gameServerConnection->send(msg); + } + else if (event.getType() == Event::DoSplit) + { + int amount = event.getInt("amount", 1); -void InventoryHandler::moveItem(int oldIndex, int newIndex) -{ - if (oldIndex == newIndex) - return; + int newIndex = PlayerInfo::getInventory()->getFreeSlot(); + if (newIndex > Inventory::NO_SLOT_INDEX) + { + MessageOut msg(PGMSG_MOVE_ITEM); + msg.writeInt8(index); + msg.writeInt8(newIndex); + msg.writeInt8(amount); + gameServerConnection->send(msg); + } + } + else if (event.getType() == Event::DoMove) + { + int newIndex = event.getInt("newIndex", -1); - MessageOut msg(PGMSG_MOVE_ITEM); - msg.writeInt8(oldIndex); - msg.writeInt8(newIndex); - msg.writeInt8(player_node->getInventory()->getItem(oldIndex) - ->getQuantity()); - gameServerConnection->send(msg); -} + if (newIndex >= 0) + { + if (index == newIndex) + return; -void InventoryHandler::openStorage(int type) -{ - // TODO -} + MessageOut msg(PGMSG_MOVE_ITEM); + msg.writeInt8(index); + msg.writeInt8(newIndex); + msg.writeInt8(item->getQuantity()); + gameServerConnection->send(msg); + } + else + { + /*int source = event.getInt("source"); + int destination = event.getInt("destination"); + int amount = event.getInt("amount", 1);*/ -void InventoryHandler::closeStorage(int type) -{ - // TODO + // TODO + } + } + } } -void InventoryHandler::moveItem(int source, int slot, int amount, - int destination) +bool InventoryHandler::canSplit(const Item *item) { - // TODO + return item && !item->getInfo().getEquippable() + && item->getQuantity() > 1; } size_t InventoryHandler::getSize(int type) const |