summaryrefslogtreecommitdiff
path: root/src/net/manaserv
diff options
context:
space:
mode:
Diffstat (limited to 'src/net/manaserv')
-rw-r--r--src/net/manaserv/inventoryhandler.cpp161
-rw-r--r--src/net/manaserv/inventoryhandler.h40
2 files changed, 166 insertions, 35 deletions
diff --git a/src/net/manaserv/inventoryhandler.cpp b/src/net/manaserv/inventoryhandler.cpp
index ff9b69e6..c8dae1c3 100644
--- a/src/net/manaserv/inventoryhandler.cpp
+++ b/src/net/manaserv/inventoryhandler.cpp
@@ -26,8 +26,11 @@
#include "item.h"
#include "itemshortcut.h"
#include "localplayer.h"
+#include "log.h"
#include "playerinfo.h"
+#include "gui/inventorywindow.h"
+
#include "net/manaserv/connection.h"
#include "net/manaserv/messagein.h"
#include "net/manaserv/messageout.h"
@@ -41,6 +44,125 @@ 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[] = {
@@ -62,21 +184,21 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
case GPMSG_INVENTORY_FULL:
{
PlayerInfo::clearInventory();
- PlayerInfo::getEquipment()->setBackend(&mEquips);
+ PlayerInfo::getEquipment()->setBackend(&mEquipBackend);
int count = msg.readInt16();
while (count--)
{
- unsigned int slot = msg.readInt16();
+ int slot = msg.readInt16();
int id = msg.readInt16();
- unsigned int amount = msg.readInt16();
+ int amount = msg.readInt16();
PlayerInfo::setInventoryItem(slot, id, amount);
}
while (msg.getUnreadLength())
{
- unsigned int slot = msg.readInt8();
- unsigned int ref = msg.readInt16();
+ int equipSlot = msg.readInt8();
+ int inventorySlot = msg.readInt16();
- mEquips.addEquipment(slot, ref);
+ mEquipBackend.equip(inventorySlot, equipSlot);
}
}
break;
@@ -94,14 +216,25 @@ void InventoryHandler::handleMessage(Net::MessageIn &msg)
case GPMSG_EQUIP:
while (msg.getUnreadLength())
{
- unsigned int ref = msg.readInt16();
- int count = msg.readInt8();
- while (count--)
+ int inventorySlot = msg.readInt16();
+ int equipSlotCount = msg.readInt8();
+
+ if (equipSlotCount == 0)
{
- unsigned int slot = msg.readInt8();
- unsigned int used = msg.readInt8();
+ // No slots means to unequip this item
+ mEquipBackend.unequip(inventorySlot);
+ }
+ else
+ {
+ // Otherwise equip the item in the given slots
+ while (equipSlotCount--)
+ {
+ unsigned int equipSlot = msg.readInt8();
+ unsigned int amountUsed = msg.readInt8();
- mEquips.setEquipment(slot, used, ref);
+ mEquipBackend.equip(inventorySlot, equipSlot,
+ amountUsed);
+ }
}
}
break;
@@ -131,10 +264,6 @@ void InventoryHandler::event(Event::Channel channel,
MessageOut msg(PGMSG_UNEQUIP);
msg.writeInt8(index);
gameServerConnection->send(msg);
-
- // Tidy equipment directly to avoid weapon still shown bug,
- // for instance.
- mEquips.setEquipment(index, 0, 0);
}
else if (event.getType() == Event::DoUse)
{
diff --git a/src/net/manaserv/inventoryhandler.h b/src/net/manaserv/inventoryhandler.h
index 2733f3da..255f601c 100644
--- a/src/net/manaserv/inventoryhandler.h
+++ b/src/net/manaserv/inventoryhandler.h
@@ -29,33 +29,35 @@
#include "net/manaserv/messagehandler.h"
+#include <vector>
+
namespace ManaServ {
-class EquipBackend : public Equipment::Backend
+class EquipBackend : public Equipment::Backend, public EventListener
{
public:
- EquipBackend()
- { memset(mEquipment, 0, sizeof(mEquipment)); }
-
- Item *getEquipment(int index) const
- { return 0; }
+ EquipBackend();
- void clear()
- {
- }
+ Item *getEquipment(int index) const;
+ void clear();
- void setEquipment(unsigned int slot, unsigned int used, int reference)
- {
- printf("Equip: %d at %dx%d\n", reference, slot, used);
- }
+ void equip(int inventorySlot, int equipSlot, int amountUsed = 1);
+ void unequip(int inventorySlot);
- void addEquipment(unsigned int slot, int reference)
- {
- printf("Equip: %d at %d\n", reference, slot);
- }
+ void event(Event::Channel channel, const Event &event);
private:
- Item *mEquipment[EQUIPMENT_SIZE];
+ void readEquipFile();
+
+ struct SlotType {
+ std::string name;
+ int count;
+ bool visible;
+ int firstIndex;
+ };
+
+ std::vector<Item*> mSlots;
+ std::vector<SlotType> mSlotTypes;
};
class InventoryHandler : public MessageHandler, Net::InventoryHandler,
@@ -73,7 +75,7 @@ class InventoryHandler : public MessageHandler, Net::InventoryHandler,
size_t getSize(int type) const;
private:
- EquipBackend mEquips;
+ EquipBackend mEquipBackend;
};
} // namespace ManaServ