summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-01-04 20:17:07 +0000
committerGuillaume Melquiond <guillaume.melquiond@gmail.com>2007-01-04 20:17:07 +0000
commite68fa3087865e369cb78cfa61c441507eedf4284 (patch)
tree72bb502abdb4fb4081ba2457be1c53ea0d1933e4
parentbbdbb95d5d477b9934bf27cb45c53afbabb2db78 (diff)
downloadmanaserv-e68fa3087865e369cb78cfa61c441507eedf4284.tar.gz
manaserv-e68fa3087865e369cb78cfa61c441507eedf4284.tar.bz2
manaserv-e68fa3087865e369cb78cfa61c441507eedf4284.tar.xz
manaserv-e68fa3087865e369cb78cfa61c441507eedf4284.zip
Server-side implementation of item pick-up.
-rw-r--r--ChangeLog5
-rw-r--r--src/defines.h4
-rw-r--r--src/game-server/gamehandler.cpp96
-rw-r--r--src/game-server/inventory.cpp76
-rw-r--r--src/game-server/inventory.hpp6
-rw-r--r--src/game-server/mapcomposite.cpp7
-rw-r--r--src/game-server/mapcomposite.hpp5
-rw-r--r--src/net/messagein.cpp28
-rw-r--r--src/net/messagein.hpp21
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 <elvenprogrammer@gmail.com>
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 <map>
#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
@@ -201,6 +201,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.
*/
ZoneIterator getAroundObjectIterator(Object *, int radius) const;
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