summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/account-server/storage.cpp42
-rw-r--r--src/common/inventorydata.h46
-rw-r--r--src/game-server/buysell.cpp6
-rw-r--r--src/game-server/inventory.cpp50
-rw-r--r--src/game-server/state.cpp8
-rw-r--r--src/serialize/characterdata.h45
-rw-r--r--src/sql/mysql/createTables.sql6
-rw-r--r--src/sql/sqlite/createTables.sql3
8 files changed, 117 insertions, 89 deletions
diff --git a/src/account-server/storage.cpp b/src/account-server/storage.cpp
index 96601207..05f8ec69 100644
--- a/src/account-server/storage.cpp
+++ b/src/account-server/storage.cpp
@@ -490,17 +490,26 @@ Character *Storage::getCharacterBySQL(Account *owner)
try
{
std::ostringstream sql;
- sql << " select slot_type, inventory_slot from "
+ sql << " select slot_type, item_id, item_instance from "
<< CHAR_EQUIPS_TBL_NAME
<< " where owner_id = '"
<< character->getDatabaseID() << "' order by slot_type desc;";
+ EquipData equipData;
const dal::RecordSet &equipInfo = mDb->execSql(sql.str());
if (!equipInfo.isEmpty())
+ {
+ EquipmentItem equipItem;
for (int k = 0, size = equipInfo.rows(); k < size; ++k)
- poss.equipSlots.insert(std::pair<unsigned int, unsigned int>(
- toUint(equipInfo(k, 0)),
- toUint(equipInfo(k, 1))));
+ {
+ equipItem.itemId = toUint(equipInfo(k, 1));
+ equipItem.itemInstance = toUint(equipInfo(k, 2));
+ equipData.insert(std::pair<unsigned int, EquipmentItem>(
+ toUint(equipInfo(k, 0)),
+ equipItem));
+ }
+ }
+ poss.setEquipment(equipData);
}
catch (const dal::DbSqlQueryExecFailure &e)
{
@@ -515,6 +524,7 @@ Character *Storage::getCharacterBySQL(Account *owner)
<< " where owner_id = '"
<< character->getDatabaseID() << "' order by slot asc;";
+ InventoryData inventoryData;
const dal::RecordSet &itemInfo = mDb->execSql(sql.str());
if (!itemInfo.isEmpty())
{
@@ -524,9 +534,10 @@ Character *Storage::getCharacterBySQL(Account *owner)
unsigned short slot = toUint(itemInfo(k, 2));
item.itemId = toUint(itemInfo(k, 3));
item.amount = toUint(itemInfo(k, 4));
- poss.inventory[slot] = item;
+ inventoryData[slot] = item;
}
}
+ poss.setInventory(inventoryData);
}
catch (const dal::DbSqlQueryExecFailure &e)
{
@@ -798,18 +809,18 @@ bool Storage::updateCharacter(Character *character)
std::ostringstream sql;
sql << "insert into " << CHAR_EQUIPS_TBL_NAME
- << " (owner_id, slot_type, inventory_slot) values ("
+ << " (owner_id, slot_type, item_id, item_instance) values ("
<< character->getDatabaseID() << ", ";
std::string base = sql.str();
const Possessions &poss = character->getPossessions();
- for (EquipData::const_iterator it = poss.equipSlots.begin(),
- it_end = poss.equipSlots.end();
- it != it_end;
- ++it)
+ const EquipData &equipData = poss.getEquipment();
+ for (EquipData::const_iterator it = equipData.begin(),
+ it_end = equipData.end(); it != it_end; ++it)
{
sql.str("");
- sql << base << it->first << ", " << it->second << ");";
+ sql << base << it->first << ", " << it->second.itemId
+ << ", " << it->second.itemInstance << ");";
mDb->execSql(sql.str());
}
@@ -820,13 +831,14 @@ bool Storage::updateCharacter(Character *character)
<< character->getDatabaseID() << ", ";
base = sql.str();
- for (InventoryData::const_iterator j = poss.inventory.begin(),
- j_end = poss.inventory.end(); j != j_end; ++j)
+ const InventoryData &inventoryData = poss.getInventory();
+ for (InventoryData::const_iterator j = inventoryData.begin(),
+ j_end = inventoryData.end(); j != j_end; ++j)
{
sql.str("");
unsigned short slot = j->first;
- unsigned int itemId = j->second.itemId;
- unsigned int amount = j->second.amount;
+ unsigned int itemId = j->second.itemId;
+ unsigned int amount = j->second.amount;
assert(itemId);
sql << base << slot << ", " << itemId << ", " << amount << ");";
mDb->execSql(sql.str());
diff --git a/src/common/inventorydata.h b/src/common/inventorydata.h
index 9127c816..e7c81170 100644
--- a/src/common/inventorydata.h
+++ b/src/common/inventorydata.h
@@ -35,20 +35,56 @@
*/
struct InventoryItem
{
+ InventoryItem():
+ itemId(0), amount(0)
+ {}
+
unsigned int itemId;
unsigned int amount;
};
-// slot id -> { item }
-typedef std::map< unsigned short, InventoryItem > InventoryData;
-// equip slot type -> { slot ids }
-// Equipment taking up multiple slots will be referenced multiple times
-typedef std::multimap< unsigned int, unsigned int > EquipData;
+
+struct EquipmentItem
+{
+ EquipmentItem():
+ itemId(0), itemInstance(0)
+ {}
+
+ // The item id taken from the item db.
+ unsigned int itemId;
+ // A unique instance number used to separate items when equipping the same
+ // item id multiple times on possible multiple slots.
+ unsigned int itemInstance;
+};
+
+// inventory slot id -> { item }
+typedef std::map< unsigned int, InventoryItem > InventoryData;
+
+// equip slot id -> { item id }
+// Equipment taking up multiple equip slot ids will be referenced multiple times
+typedef std::multimap< unsigned int, EquipmentItem > EquipData;
/**
* Structure storing the equipment and inventory of a Player.
*/
struct Possessions
{
+ friend class Inventory;
+public:
+ const EquipData &getEquipment() const
+ { return equipSlots; }
+
+ const InventoryData &getInventory() const
+ { return inventory; }
+
+ /**
+ * Should be done only at character serialization and storage load time.
+ */
+ void setEquipment(EquipData &equipData)
+ { equipSlots.swap(equipData); }
+ void setInventory(InventoryData &inventoryData)
+ { inventory.swap(inventoryData); }
+
+private:
InventoryData inventory;
EquipData equipSlots;
};
diff --git a/src/game-server/buysell.cpp b/src/game-server/buysell.cpp
index a9658546..78c2bfe0 100644
--- a/src/game-server/buysell.cpp
+++ b/src/game-server/buysell.cpp
@@ -72,9 +72,9 @@ int BuySell::registerPlayerItems()
// We parse the player inventory and add all item
// in a sell list.
- const Possessions &charPoss = mChar->getPossessions();
- for (InventoryData::const_iterator it = charPoss.inventory.begin(),
- it_end = charPoss.inventory.end(); it != it_end; ++it)
+ const InventoryData &inventoryData = mChar->getPossessions().getInventory();
+ for (InventoryData::const_iterator it = inventoryData.begin(),
+ it_end = inventoryData.end(); it != it_end; ++it)
{
unsigned int nb = it->second.amount;
if (!nb)
diff --git a/src/game-server/inventory.cpp b/src/game-server/inventory.cpp
index e218a916..8689f299 100644
--- a/src/game-server/inventory.cpp
+++ b/src/game-server/inventory.cpp
@@ -54,8 +54,9 @@ void Inventory::sendFull() const
k != k_end;
++k)
{
- m.writeInt8(k->first); // equip slot
- m.writeInt16(k->second); // inventory slot
+ m.writeInt16(k->first); // Equip slot id
+ m.writeInt16(k->second.itemId); // Item id
+ m.writeInt16(k->second.itemInstance); // Item instance
}
gameHandler->sendTo(mCharacter, m);
@@ -106,7 +107,7 @@ void Inventory::initialize()
*/
for (it2 = mPoss->equipSlots.begin(); it2 != it2_end; ++it2)
{
- if (equipment.insert(it2->second).second)
+ if (equipment.insert(it2->second.itemInstance).second)
{
/*
* Perform checks for equipped items
@@ -117,7 +118,7 @@ void Inventory::initialize()
/*
* Apply all equip triggers.
*/
- itemManager->getItem(mPoss->inventory.at(it2->second).itemId)
+ itemManager->getItem(it2->second.itemId)
->useTrigger(mCharacter, ITT_EQUIP);
}
}
@@ -239,8 +240,7 @@ unsigned int Inventory::count(unsigned int itemId) const
unsigned int Inventory::remove(unsigned int itemId, unsigned int amount, bool force)
{
- bool inv = false,
- eq = !itemManager->getItem(itemId)->getItemEquipData().empty();
+ bool inv = false;
MessageOut invMsg(GPMSG_INVENTORY);
bool triggerLeaveInventory = true;
@@ -251,26 +251,6 @@ unsigned int Inventory::remove(unsigned int itemId, unsigned int amount, bool fo
{
if (amount)
{
- if (eq)
- {
- // If the item is equippable,
- // we have additional checks to make.
- bool ch = false;
- for (EquipData::iterator it2 = mPoss->equipSlots.begin(),
- it2_end = mPoss->equipSlots.end();
- it2 != it2_end;
- ++it2)
- if (it2->second == it->first)
- {
- if (force)
- unequip(it2);
- else
- ch = inv = true;
- break;
- }
- if (ch && !force)
- continue;
- }
unsigned int sub = std::min(amount, it->second.amount);
amount -= sub;
it->second.amount -= sub;
@@ -320,15 +300,6 @@ unsigned int Inventory::move(unsigned int slot1, unsigned int slot2,
if (it1 == inv_end)
return amount;
- EquipData::iterator it, it_end = mPoss->equipSlots.end();
- for (it = mPoss->equipSlots.begin();
- it != it_end;
- ++it)
- if (it->second == slot1)
- // Bad things will happen when you can stack multiple equippable
- // items in the same slot anyway.
- it->second = slot2;
-
MessageOut invMsg(GPMSG_INVENTORY);
unsigned int nb = std::min(amount, it1->second.amount);
@@ -538,9 +509,10 @@ bool Inventory::equip(int slot, bool override)
* compile time options optimising for other usage.
* For now, this is adequate assuming `normal' usage.
*/
- for (unsigned int i = 0; i < it3->second; ++i)
+ /** Part disabled until reimplemented*/
+ /*for (unsigned int i = 0; i < it3->second; ++i)
mPoss->equipSlots.insert(
- std::make_pair(it3->first, slot));
+ std::make_pair(it3->first, slot));*/
}
changeEquipment(0, it->second.itemId);
@@ -598,7 +570,7 @@ bool Inventory::equip(int slot, bool override)
bool Inventory::unequip(EquipData::iterator it)
{
- return unequip(it->second, &it);
+ return unequip(it->first, &it);
}
bool Inventory::unequip(unsigned int slot, EquipData::iterator *itp)
@@ -611,7 +583,7 @@ bool Inventory::unequip(unsigned int slot, EquipData::iterator *itp)
// Erase all equip entries that point to the given inventory slot
while (it != it_end)
{
- if (it->second == slot)
+ if (it->first == slot)
{
changed = true;
mPoss->equipSlots.erase(it++);
diff --git a/src/game-server/state.cpp b/src/game-server/state.cpp
index 03d4b71c..1a9c0204 100644
--- a/src/game-server/state.cpp
+++ b/src/game-server/state.cpp
@@ -108,7 +108,7 @@ static void updateMap(MapComposite *map)
*/
static void serializeLooks(Character *ch, MessageOut &msg, bool full)
{
- const Possessions &poss = ch->getPossessions();
+ const EquipData &equipData = ch->getPossessions().getEquipment();
unsigned int nb_slots = itemManager->getVisibleSlotCount();
// Bitmask describing the changed entries.
@@ -125,8 +125,8 @@ static void serializeLooks(Character *ch, MessageOut &msg, bool full)
// Partially build both kinds of packet, to get their sizes.
unsigned int mask_full = 0, mask_diff = 0;
unsigned int nb_full = 0, nb_diff = 0;
- std::map<unsigned int, unsigned int>::const_iterator it =
- poss.equipSlots.begin();
+ std::map<unsigned int, EquipmentItem>::const_iterator it =
+ equipData.begin();
for (unsigned int i = 0; i < nb_slots; ++i)
{
if (changed & (1 << i))
@@ -135,7 +135,7 @@ static void serializeLooks(Character *ch, MessageOut &msg, bool full)
++nb_diff;
mask_diff |= 1 << i;
}
- if (it == poss.equipSlots.end() || it->first > i) continue;
+ if (it == equipData.end() || it->first > i) continue;
ItemClass *eq;
items[i] = it->first && (eq = itemManager->getItem(it->first)) ?
eq->getSpriteID() : 0;
diff --git a/src/serialize/characterdata.h b/src/serialize/characterdata.h
index 4466c98e..c453e685 100644
--- a/src/serialize/characterdata.h
+++ b/src/serialize/characterdata.h
@@ -97,20 +97,22 @@ void serializeCharacterData(const T &data, MessageOut &msg)
// inventory - must be last because size isn't transmitted
const Possessions &poss = data.getPossessions();
- msg.writeInt16(poss.equipSlots.size()); // number of equipment
- for (EquipData::const_iterator k = poss.equipSlots.begin(),
- k_end = poss.equipSlots.end();
- k != k_end;
- ++k)
+ const EquipData &equipData = poss.getEquipment();
+ msg.writeInt16(equipData.size()); // number of equipment
+ for (EquipData::const_iterator k = equipData.begin(),
+ k_end = equipData.end(); k != k_end; ++k)
{
- msg.writeInt8(k->first); // Equip slot type
- msg.writeInt16(k->second); // Inventory slot
+ msg.writeInt16(k->first); // Equip slot id
+ msg.writeInt16(k->second.itemId); // ItemId
+ msg.writeInt16(k->second.itemInstance); // Item Instance id
}
- for (InventoryData::const_iterator j = poss.inventory.begin(),
- j_end = poss.inventory.end(); j != j_end; ++j)
+
+ const InventoryData &inventoryData = poss.getInventory();
+ for (InventoryData::const_iterator j = inventoryData.begin(),
+ j_end = inventoryData.end(); j != j_end; ++j)
{
msg.writeInt16(j->first); // slot id
- msg.writeInt16(j->second.itemId); // item type
+ msg.writeInt16(j->second.itemId); // item id
msg.writeInt16(j->second.amount); // amount
}
}
@@ -185,26 +187,31 @@ void deserializeCharacterData(T &data, MessageIn &msg)
Possessions &poss = data.getPossessions();
- poss.equipSlots.clear();
+ EquipData equipData;
int equipSlotsSize = msg.readInt16();
- unsigned int eqSlot, invSlot;
+ unsigned int eqSlot;
+ EquipmentItem equipItem;
for (int j = 0; j < equipSlotsSize; ++j)
{
- eqSlot = msg.readInt8();
- invSlot = msg.readInt16();
- poss.equipSlots.insert(poss.equipSlots.end(),
- std::make_pair(eqSlot, invSlot));
+ eqSlot = msg.readInt16();
+ equipItem.itemId = msg.readInt16();
+ equipItem.itemInstance = msg.readInt16();
+ equipData.insert(equipData.end(),
+ std::make_pair(eqSlot, equipItem));
}
- poss.inventory.clear();
- // inventory - must be last because size isn't transmitted
+ poss.setEquipment(equipData);
+
+ // Loads inventory - must be last because size isn't transmitted
+ InventoryData inventoryData;
while (msg.getUnreadLength())
{
InventoryItem i;
int slotId = msg.readInt16();
i.itemId = msg.readInt16();
i.amount = msg.readInt16();
- poss.inventory.insert(poss.inventory.end(), std::make_pair(slotId, i));
+ inventoryData.insert(inventoryData.end(), std::make_pair(slotId, i));
}
+ poss.setInventory(inventoryData);
}
#endif // SERIALIZE_CHARACTERDATA_H
diff --git a/src/sql/mysql/createTables.sql b/src/sql/mysql/createTables.sql
index 9e1e31a6..d017ceee 100644
--- a/src/sql/mysql/createTables.sql
+++ b/src/sql/mysql/createTables.sql
@@ -184,11 +184,11 @@ AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `mana_char_equips` (
`id` int(10) unsigned NOT NULL auto_increment,
`owner_id` int(10) unsigned NOT NULL,
- `slot_type` tinyint(3) unsigned NOT NULL,
- `inventory_slot` tinyint(3) unsigned NOT NULL,
+ `slot_type` int(10) unsigned NOT NULL,
+ `item_id` int(10) unsigned NOT NULL,
+ `item_instance` int(10) unsigned NOT NULL,
--
PRIMARY KEY (`id`),
- UNIQUE KEY `owner_id` (`owner_id`, `inventory_slot`),
FOREIGN KEY (`owner_id`) REFERENCES `mana_characters` (`id`)
) ENGINE=InnoDB
DEFAULT CHARSET=utf8;
diff --git a/src/sql/sqlite/createTables.sql b/src/sql/sqlite/createTables.sql
index b366606b..1027b580 100644
--- a/src/sql/sqlite/createTables.sql
+++ b/src/sql/sqlite/createTables.sql
@@ -178,7 +178,8 @@ CREATE TABLE mana_char_equips
id INTEGER PRIMARY KEY,
owner_id INTEGER NOT NULL,
slot_type INTEGER NOT NULL,
- inventory_slot INTEGER NOT NULL,
+ item_id INTEGER NOT NULL,
+ item_instance INTEGER NOT NULL,
--
FOREIGN KEY (owner_id) REFERENCES mana_characters(id)
);