summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog10
-rw-r--r--src/defines.h1
-rw-r--r--src/game-server/gamehandler.cpp8
-rw-r--r--src/game-server/inventory.cpp147
-rw-r--r--src/game-server/inventory.hpp6
-rw-r--r--src/game-server/state.cpp2
-rw-r--r--src/net/messageout.cpp11
-rw-r--r--src/net/messageout.hpp11
8 files changed, 180 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 6150b991..b8559f00 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2007-08-08 Guillaume Melquiond <guillaume.melquiond@gmail.com>
+
+ * src/net/messageout.hpp, src/net/messageout.cpp: Changed argument
+ types to generic int.
+ * src/game-server/inventory.cpp, src/game-server/inventory.hpp,
+ src/defines.h, src/game-server/gamehandler.cpp: Added protocol for
+ moving objects between slots of inventory.
+ * src/game-server/state.cpp: Fixed position of the cleaning bit for
+ looks, so that it actually fits into network data.
+
2007-08-01 Guillaume Melquiond <guillaume.melquiond@gmail.com>
* src/game-server/itemmanager.cpp: Ensured equipment items cannot
diff --git a/src/defines.h b/src/defines.h
index 2fe6efba..3e172489 100644
--- a/src/defines.h
+++ b/src/defines.h
@@ -146,6 +146,7 @@ enum {
PGMSG_DROP = 0x0111, // B slot, B amount
PGMSG_EQUIP = 0x0112, // B slot
PGMSG_UNEQUIP = 0x0113, // B slot
+ PGMSG_MOVE_ITEM = 0x0114, // B slot1, B slot2, B amount
GPMSG_INVENTORY = 0x0120, // { B slot, W item id [, B amount] }*
GPMSG_INVENTORY_FULL = 0x0121, // { B slot, W item id [, B amount] }*
GPMSG_PLAYER_ATTRIBUTE_UPDATE = 0x0130, // { W attribute, W value }*
diff --git a/src/game-server/gamehandler.cpp b/src/game-server/gamehandler.cpp
index e01c4a9d..17ce6dee 100644
--- a/src/game-server/gamehandler.cpp
+++ b/src/game-server/gamehandler.cpp
@@ -259,6 +259,14 @@ void GameHandler::processMessage(NetComputer *comp, MessageIn &message)
}
} break;
+ case PGMSG_MOVE_ITEM:
+ {
+ int slot1 = message.readByte();
+ int slot2 = message.readByte();
+ int amount = message.readByte();
+ Inventory(computer.character).move(slot1, slot2, amount);
+ } break;
+
case PGMSG_ATTACK:
{
LOG_DEBUG("Character " << computer.character->getPublicID()
diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp
index 50e229cc..49442a5c 100644
--- a/src/game-server/inventory.cpp
+++ b/src/game-server/inventory.cpp
@@ -162,12 +162,13 @@ int Inventory::getItem(int slot) const
int Inventory::getIndex(int slot) const
{
int index = 0;
+
for (std::vector< InventoryItem >::const_iterator i = mPoss->inventory.begin(),
i_end = mPoss->inventory.end(); i != i_end; ++i, ++index)
{
if (slot == 0)
{
- return index;
+ return i->itemId ? index : -1;
}
slot -= i->itemId ? 1 : i->amount;
@@ -379,6 +380,150 @@ int Inventory::remove(int itemId, int amount)
return amount;
}
+int Inventory::move(int slot1, int slot2, int amount)
+{
+ if (amount == 0 || slot2 >= INVENTORY_SLOTS)
+ {
+ return amount;
+ }
+
+ int i1 = getIndex(slot1);
+ if (i1 < 0)
+ {
+ return amount;
+ }
+
+ prepare();
+
+ InventoryItem &it1 = mPoss->inventory[i1];
+ int i2 = getIndex(slot2);
+
+ if (i2 >= 0)
+ {
+ InventoryItem &it2 = mPoss->inventory[i2];
+ if (it1.itemId == it2.itemId)
+ {
+ // Move between two stacks of the same kind.
+ int nb = std::min(std::min(amount, (int)it1.amount), 255 - it2.amount);
+ if (nb == 0)
+ {
+ return amount;
+ }
+
+ it1.amount -= nb;
+ it2.amount += nb;
+ amount -= nb;
+
+ msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY);
+ if (it1.amount == 0)
+ {
+ msg.writeShort(0);
+ freeIndex(i1);
+ }
+ else
+ {
+ msg.writeShort(it1.itemId);
+ msg.writeByte(it1.amount);
+ }
+
+ msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY);
+ msg.writeShort(it2.itemId);
+ msg.writeByte(it2.amount);
+ return amount;
+ }
+
+ // Swap between two different stacks.
+
+ if (it1.amount != amount)
+ {
+ return amount;
+ }
+
+ std::swap(it1, it2);
+
+ msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY);
+ msg.writeShort(it1.itemId);
+ msg.writeByte(it1.amount);
+ msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY);
+ msg.writeShort(it2.itemId);
+ msg.writeByte(it2.amount);
+ return 0;
+ }
+
+ // Move some items to an empty slot.
+ int id = it1.itemId;
+ int nb = std::min((int)it1.amount, amount);
+ it1.amount -= nb;
+ amount -= nb;
+
+ msg.writeByte(slot1 + EQUIP_CLIENT_INVENTORY);
+ if (it1.amount == 0)
+ {
+ msg.writeShort(0);
+ freeIndex(i1);
+ }
+ else
+ {
+ msg.writeShort(id);
+ msg.writeByte(it1.amount);
+ }
+
+ // Fill second slot.
+ for (std::vector< InventoryItem >::iterator i = mPoss->inventory.begin(),
+ i_end = mPoss->inventory.end(); i != i_end; ++i)
+ {
+ if (i->itemId)
+ {
+ --slot2;
+ continue;
+ }
+
+ if (slot2 >= i->amount)
+ {
+ slot2 -= i->amount;
+ continue;
+ }
+
+ assert(slot2 >= 0 && i + 1 != i_end);
+
+ if (i->amount == 1)
+ {
+ // One single empty slot in the range.
+ i->itemId = id;
+ i->amount = nb;
+ break;
+ }
+
+ InventoryItem it = { id, nb };
+ --i->amount;
+
+ if (slot2 == 0)
+ {
+ // First slot in an empty range.
+ mPoss->inventory.insert(i + 1, it);
+ break;
+ }
+
+ if (slot2 == i->amount)
+ {
+ // Last slot in an empty range.
+ mPoss->inventory.insert(i, it);
+ break;
+ }
+
+ InventoryItem it3 = { 0, slot2 };
+ i->amount -= slot2;
+ i = mPoss->inventory.insert(i, it);
+ mPoss->inventory.insert(i, it3);
+ break;
+ }
+
+ msg.writeByte(slot2 + EQUIP_CLIENT_INVENTORY);
+ msg.writeShort(id);
+ msg.writeByte(nb);
+ return amount;
+}
+
int Inventory::removeFromSlot(int slot, int amount)
{
if (amount == 0)
diff --git a/src/game-server/inventory.hpp b/src/game-server/inventory.hpp
index c9a2643d..1f2611eb 100644
--- a/src/game-server/inventory.hpp
+++ b/src/game-server/inventory.hpp
@@ -123,6 +123,12 @@ class Inventory
int remove(int itemId, int amount);
/**
+ * Moves some items from the first slot to the second one.
+ * @returns number of items not moved.
+ */
+ int move(int slot1, int slot2, int amount);
+
+ /**
* Removes some items from inventory.
* @return number of items not removed.
*/
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index 19c3ea60..513f7e6e 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -138,7 +138,7 @@ static void serializeLooks(Character *ch, MessageOut &msg, bool full)
/* Bitmask enumerating the sent slots.
Setting the upper bit tells the client to clear the slots beforehand. */
- int mask = full ? mask_full | (1 << 8) : mask_diff;
+ int mask = full ? mask_full | (1 << 7) : mask_diff;
msg.writeByte(mask);
for (int i = 0; i < nb_slots; ++i)
diff --git a/src/net/messageout.cpp b/src/net/messageout.cpp
index 57b2db78..7753d9d3 100644
--- a/src/net/messageout.cpp
+++ b/src/net/messageout.cpp
@@ -43,7 +43,7 @@ MessageOut::MessageOut():
mDataSize = INITIAL_DATA_CAPACITY;
}
-MessageOut::MessageOut(short id):
+MessageOut::MessageOut(int id):
mPos(0)
{
mData = (char*) malloc(INITIAL_DATA_CAPACITY);
@@ -79,16 +79,14 @@ MessageOut::expand(size_t bytes)
}
}
-void
-MessageOut::writeByte(char value)
+void MessageOut::writeByte(int value)
{
expand(mPos + 1);
mData[mPos] = value;
mPos += 1;
}
-void
-MessageOut::writeShort(short value)
+void MessageOut::writeShort(int value)
{
expand(mPos + 2);
uint16_t t = ENET_HOST_TO_NET_16(value);
@@ -96,8 +94,7 @@ MessageOut::writeShort(short value)
mPos += 2;
}
-void
-MessageOut::writeLong(long value)
+void MessageOut::writeLong(int value)
{
expand(mPos + 4);
uint32_t t = ENET_HOST_TO_NET_32(value);
diff --git a/src/net/messageout.hpp b/src/net/messageout.hpp
index 3515476f..2d0490f6 100644
--- a/src/net/messageout.hpp
+++ b/src/net/messageout.hpp
@@ -40,7 +40,7 @@ class MessageOut
/**
* Constructor that takes a message ID.
*/
- MessageOut(short id);
+ MessageOut(int id);
/**
* Destructor.
@@ -52,14 +52,11 @@ class MessageOut
*/
void clear();
- void
- writeByte(char value); /**< Writes a byte. */
+ void writeByte(int value); /**< Writes an integer on one byte. */
- void
- writeShort(short value); /**< Writes a short. */
+ void writeShort(int value); /**< Writes an integer on two bytes. */
- void
- writeLong(long value); /**< Writes a long. */
+ void writeLong(int value); /**< Writes an integer on four bytes. */
/**
* Writes a 3-byte block containing tile-based coordinates.