From e68fa3087865e369cb78cfa61c441507eedf4284 Mon Sep 17 00:00:00 2001 From: Guillaume Melquiond Date: Thu, 4 Jan 2007 20:17:07 +0000 Subject: Server-side implementation of item pick-up. --- ChangeLog | 5 +++ src/defines.h | 4 +- src/game-server/gamehandler.cpp | 96 +++++++++++++++++++--------------------- src/game-server/inventory.cpp | 76 ++++++++++++++++++++++++------- src/game-server/inventory.hpp | 6 +-- src/game-server/mapcomposite.cpp | 7 +++ src/game-server/mapcomposite.hpp | 5 +++ src/net/messagein.cpp | 28 ++++++------ src/net/messagein.hpp | 21 ++++----- 9 files changed, 148 insertions(+), 100 deletions(-) diff --git a/ChangeLog b/ChangeLog index 745ac098..ab851eba 100644 --- a/ChangeLog +++ b/ChangeLog @@ -14,6 +14,11 @@ storing empty slots. * src/game-server/player.hpp, src/game-server/player.cpp, src/game-server/gamehandler.cpp: Updated accordingly. + * src/net/messagein.hpp, src/net/messagein.cpp: Removed signedness + interpretation of received data. + * src/game-server/mapcomposite.hpp, src/game-server/mapcomposite.cpp: + Added iterator around a point. + * src/defines.h, src/game-server/gamehandler.cpp: Implemented pick-up. 2007-01-04 Eugenio Favalli diff --git a/src/defines.h b/src/defines.h index 6cceeaa8..049eba3d 100644 --- a/src/defines.h +++ b/src/defines.h @@ -136,8 +136,8 @@ enum { // Game GPMSG_PLAYER_MAP_CHANGE = 0x0100, // S filename, W x, W y GPMSG_PLAYER_SERVER_CHANGE = 0x0101, // B*32 token, S game address, W game port - PGMSG_PICKUP = 0x0110, - GPMSG_PICKUP_RESPONSE = 0x0111, + PGMSG_PICKUP = 0x0110, // W*2 position + GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount ] }* GPMSG_BEING_ENTER = 0x0200, // B type, W being id // player: S name, B hair style, B hair color, B gender // monster: W type id diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp index 7478e8d1..54d3a224 100644 --- a/src/game-server/gamehandler.cpp +++ b/src/game-server/gamehandler.cpp @@ -25,7 +25,9 @@ #include #include "game-server/gamehandler.hpp" +#include "game-server/item.hpp" #include "game-server/map.hpp" +#include "game-server/mapcomposite.hpp" #include "game-server/state.hpp" #include "net/messagein.hpp" #include "net/messageout.hpp" @@ -226,68 +228,62 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message) switch (message.getId()) { case PGMSG_SAY: - { - std::string say = message.readString(); - gameState->sayAround(computer.character, say); - } break; + { + std::string say = message.readString(); + gameState->sayAround(computer.character, say); + } break; case PGMSG_PICKUP: - { - /* - // add item to inventory (this is too simplistic atm) - int itemId = message.readLong(); - - // remove the item from world map - - // send feedback - computer.character->insertItem(itemId, 1); - result.writeShort(GPMSG_PICKUP_RESPONSE); - result.writeByte(ERRMSG_OK); - */ - } break; + { + int x = message.readShort(); + int y = message.readShort(); + Point ppos = computer.character->getPosition(); - case PGMSG_USE_ITEM: + // TODO: use a less arbitrary value. + if (std::abs(x - ppos.x) + std::abs(y - ppos.y) < 48) { - /* - int itemId = message.readLong(); - - result.writeShort(GPMSG_USE_RESPONSE); - - if (computer.character->hasItem(itemId)) { - // use item - // this should execute a script which will do the appropriate action - // (the script will determine if the item is 1 use only) - result.writeByte(ERRMSG_OK); - } else { - result.writeByte(ERRMSG_FAILURE); + int mapId = computer.character->getMapId(); + MapComposite *map = gameState->getMap(mapId); + Point ipos = { x, y }; + for (FixedObjectIterator i(map->getAroundPointIterator(ipos, 0)); i; ++i) + { + Object *o = *i; + Point opos = o->getPosition(); + if (o->getType() == OBJECT_ITEM && opos.x == x && opos.y == y) + { + ItemClass *item = static_cast< Item * >(o)->getItemClass(); + Inventory(computer.character, result).insert(item->getDatabaseID(), 1); + gameState->remove(o); + break; + } } - */ - } break; + } + } break; case PGMSG_WALK: - { - unsigned x = message.readShort(); - unsigned y = message.readShort(); - Point dst = {x, y}; - computer.character->setDestination(dst); + { + int x = message.readShort(); + int y = message.readShort(); + Point dst = {x, y}; + computer.character->setDestination(dst); - // no response should be required - } break; + // no response should be required + } break; case PGMSG_EQUIP: - { - int slot = message.readByte(); - result.writeShort(GPMSG_EQUIP_RESPONSE); // TODO: something else - Inventory(computer.character, result).equip(slot); - } break; + { + int slot = message.readByte(); + result.writeShort(GPMSG_INVENTORY); + Inventory(computer.character, result).equip(slot); + } break; case PGMSG_ATTACK: - { - LOG_DEBUG("Player " << computer.character->getPublicID() - << " attacks", 0); - computer.character->setDirection(message.readByte()); - computer.character->setAttacking(true); - } break; + { + LOG_DEBUG("Player " << computer.character->getPublicID() + << " attacks", 0); + computer.character->setDirection(message.readByte()); + computer.character->setAttacking(true); + } break; default: LOG_WARN("Invalid message type", 0); diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp index 4807d4ff..b7e5e881 100644 --- a/src/game-server/inventory.cpp +++ b/src/game-server/inventory.cpp @@ -26,6 +26,7 @@ #include "game-server/inventory.hpp" #include "game-server/itemmanager.hpp" +#include "net/messageout.hpp" int Inventory::getItem(int slot) { @@ -68,6 +69,17 @@ int Inventory::getIndex(int slot) return -1; } +int Inventory::getSlot(int index) +{ + int slot = 0; + for (std::vector< InventoryItem >::iterator i = poss.inventory.begin(), + i_end = poss.inventory.begin() + index; i != i_end; ++i) + { + slot += i->itemId ? 1 : i->amount; + } + return slot; +} + int Inventory::fillFreeSlot(int itemId, int amount, int maxPerSlot) { int slot = 0; @@ -90,7 +102,10 @@ int Inventory::fillFreeSlot(int itemId, int amount, int maxPerSlot) ++i_end; } - // TODO: fill msg + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(itemId); + msg.writeByte(nb); + amount -= nb; if (amount == 0) { @@ -106,8 +121,11 @@ int Inventory::fillFreeSlot(int itemId, int amount, int maxPerSlot) amount -= nb; InventoryItem it = { itemId, nb }; poss.inventory.push_back(it); + + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(itemId); + msg.writeByte(nb); ++slot; - // TODO: fill msg } return amount; @@ -115,6 +133,7 @@ int Inventory::fillFreeSlot(int itemId, int amount, int maxPerSlot) int Inventory::insert(int itemId, int amount) { + int slot = 0; int maxPerSlot = itemManager->getItem(itemId)->getMaxPerSlot(); for (std::vector< InventoryItem >::iterator i = poss.inventory.begin(), @@ -125,11 +144,20 @@ int Inventory::insert(int itemId, int amount) int nb = std::min(maxPerSlot - i->amount, amount); i->amount += nb; amount -= nb; - // TODO: fill msg + + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(itemId); + msg.writeByte(nb); + if (amount == 0) { return 0; } + ++slot; + } + else + { + slot += i->itemId ? 1 : i->amount; } } @@ -174,7 +202,10 @@ int Inventory::remove(int itemId, int amount) int nb = std::min((int)it.amount, amount); it.amount -= nb; amount -= nb; - // TODO: fill msg + + msg.writeByte(getSlot(i) + EQUIP_CLIENT_INVENTORY); + msg.writeShort(itemId); + msg.writeByte(nb); // If the slot is empty, compress the inventory. if (it.amount == 0) @@ -205,31 +236,36 @@ bool Inventory::equip(int slot) switch (itemManager->getItem(itemId)->getType()) { case ITEM_EQUIPMENT_TWO_HANDS_WEAPON: + { // Special case 1, the two one-handed weapons are to be placed back // in the inventory, if there are any. - if (int id = poss.equipment[EQUIP_FIGHT1_SLOT]) + int id = poss.equipment[EQUIP_FIGHT1_SLOT]; + if (id && !insert(id, 1)) { - // Slot 1 full - if (!insert(id, 1)) - { - return false; - } + return false; } - if (int id = poss.equipment[EQUIP_FIGHT2_SLOT]) + + id = poss.equipment[EQUIP_FIGHT2_SLOT]; + if (id && !insert(id, 1)) { - // Slot 2 full - if (!insert(id, 1)) - { - return false; - } + return false; } + msg.writeByte(EQUIP_FIGHT1_SLOT); + msg.writeShort(itemId); + msg.writeByte(EQUIP_FIGHT2_SLOT); + msg.writeShort(0); + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(0); poss.equipment[EQUIP_FIGHT1_SLOT] = itemId; poss.equipment[EQUIP_FIGHT2_SLOT] = 0; freeIndex(getIndex(slot)); return true; + } case ITEM_EQUIPMENT_PROJECTILE: + msg.writeByte(EQUIP_PROJECTILE_SLOT); + msg.writeShort(itemId); poss.equipment[EQUIP_PROJECTILE_SLOT] = itemId; return true; @@ -285,6 +321,10 @@ bool Inventory::equip(int slot) ITEM_EQUIPMENT_TWO_HANDS_WEAPON) { // The first slot is full and the second slot is empty. + msg.writeByte(secondSlot); + msg.writeShort(itemId); + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(0); poss.equipment[secondSlot] = itemId; freeIndex(getIndex(slot)); return true; @@ -296,6 +336,10 @@ bool Inventory::equip(int slot) { return false; } + msg.writeByte(firstSlot); + msg.writeShort(itemId); + msg.writeByte(slot + EQUIP_CLIENT_INVENTORY); + msg.writeShort(0); poss.equipment[firstSlot] = itemId; freeIndex(getIndex(slot)); return true; diff --git a/src/game-server/inventory.hpp b/src/game-server/inventory.hpp index 87c1010c..3640abc3 100644 --- a/src/game-server/inventory.hpp +++ b/src/game-server/inventory.hpp @@ -54,10 +54,7 @@ enum // this item does not amount to one, it only indicates the chosen projectile. EQUIP_PROJECTILE_SLOT = 10, -// Error codes - NOT_EQUIPPABLE = 253, - NO_ITEM_TO_EQUIP = 254, - INVENTORY_FULL = 255 + EQUIP_CLIENT_INVENTORY = 32 }; class MessageOut; @@ -107,6 +104,7 @@ class Inventory void freeIndex(int index); int getItem(int slot); int getIndex(int slot); + int getSlot(int index); }; diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 2ccee600..043c7fa6 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -408,6 +408,13 @@ void MapComposite::fillRegion(MapRegion &r, Rectangle const &p) const } } +ZoneIterator MapComposite::getAroundPointIterator(Point const &p, int radius) const +{ + MapRegion r; + fillRegion(r, p, radius); + return ZoneIterator(r, this); +} + ZoneIterator MapComposite::getAroundObjectIterator(Object *obj, int radius) const { MapRegion r; diff --git a/src/game-server/mapcomposite.hpp b/src/game-server/mapcomposite.hpp index 0eae7d91..89f10c00 100644 --- a/src/game-server/mapcomposite.hpp +++ b/src/game-server/mapcomposite.hpp @@ -200,6 +200,11 @@ class MapComposite { */ ZoneIterator getInsideRectangleIterator(Rectangle const &) const; + /** + * Gets an iterator on the objects around a given point. + */ + ZoneIterator getAroundPointIterator(Point const &, int radius) const; + /** * Gets an iterator on the objects around a given object. */ diff --git a/src/net/messagein.cpp b/src/net/messagein.cpp index 8da02550..783cbf11 100644 --- a/src/net/messagein.cpp +++ b/src/net/messagein.cpp @@ -35,37 +35,33 @@ MessageIn::MessageIn(const char *data, int length): mId = readShort(); } -MessageIn::~MessageIn() +int MessageIn::readByte() { -} - -char MessageIn::readByte() -{ - char value = -1; + int value = -1; if (mPos < mLength) { - value = mData[mPos]; + value = (unsigned char)mData[mPos]; } mPos += 1; return value; } -short MessageIn::readShort() +int MessageIn::readShort() { - short value = -1; + int value = -1; if (mPos + 2 <= mLength) { uint16_t t; memcpy(&t, mData + mPos, 2); - value = ENET_NET_TO_HOST_16(t); + value = (unsigned short)ENET_NET_TO_HOST_16(t); } mPos += 2; return value; } -long MessageIn::readLong() +int MessageIn::readLong() { - long value = -1; + int value = -1; if (mPos + 4 <= mLength) { uint32_t t; @@ -79,14 +75,16 @@ long MessageIn::readLong() std::string MessageIn::readString(int length) { // Get string length - if (length < 0) { + if (length < 0) + { length = readShort(); } // Make sure the string isn't erroneous - if (length < 0 || mPos + length > mLength) { + if (length < 0 || mPos + length > mLength) + { mPos = mLength + 1; - return ""; + return std::string(); } // Read the string diff --git a/src/net/messagein.hpp b/src/net/messagein.hpp index c582d056..79063f97 100644 --- a/src/net/messagein.hpp +++ b/src/net/messagein.hpp @@ -39,16 +39,11 @@ class MessageIn */ MessageIn(const char *data, int length); - /** - * Destructor. - */ - ~MessageIn(); - - short getId() { return mId; } /**< Returns the message ID. */ + int getId() { return mId; } /**< Returns the message ID. */ - char readByte(); /**< Reads a byte. */ - short readShort(); /**< Reads a short. */ - long readLong(); /**< Reads a long. */ + int readByte(); /**< Reads a byte. */ + int readShort(); /**< Reads a short. */ + int readLong(); /**< Reads a long. */ /** * Reads a string. If a length is not given (-1), it is assumed @@ -60,18 +55,18 @@ class MessageIn /** * Returns the length of unread data. */ - unsigned getUnreadLength() { return mLength - mPos; } + int getUnreadLength() { return mLength - mPos; } private: const char *mData; /**< Packet data */ - unsigned int mLength; /**< Length of data in bytes */ - short mId; /**< The message ID. */ + unsigned short mLength; /**< Length of data in bytes */ + unsigned short mId; /**< The message ID. */ /** * Actual position in the packet. From 0 to packet->length. A value * bigger than packet->length means EOP was reached when reading it. */ - unsigned int mPos; + unsigned short mPos; }; #endif -- cgit v1.2.3-60-g2f50