mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-28 04:41:30 +00:00
Swap saving now works correctly except for cursor items which wont be reloaded correctly as we don't send cursor on login yet. Also added check for bag into another bag src bag needs to have nothing in it first.
This commit is contained in:
parent
972d3d8874
commit
9fcdf5367e
@ -31,6 +31,7 @@ SET(common_sources
|
||||
guild_base.cpp
|
||||
guilds.cpp
|
||||
inventory.cpp
|
||||
inventory_db_data_model.cpp
|
||||
ipc_mutex.cpp
|
||||
item.cpp
|
||||
item_container.cpp
|
||||
@ -143,6 +144,7 @@ SET(common_headers
|
||||
guilds.h
|
||||
inventory.h
|
||||
inventory_data_model.h
|
||||
inventory_db_data_model.h
|
||||
inventory_null_data_model.h
|
||||
ipc_mutex.h
|
||||
item.h
|
||||
|
||||
@ -151,7 +151,7 @@ void EQEmu::Inventory::SetDeity(int deity) {
|
||||
impl_->deity_ = deity;
|
||||
}
|
||||
|
||||
void EQEmu::Inventory::SetDataMode(InventoryDataModel *dm) {
|
||||
void EQEmu::Inventory::SetDataModel(InventoryDataModel *dm) {
|
||||
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(dm);
|
||||
}
|
||||
|
||||
@ -236,6 +236,12 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i_src->GetBaseItem()->ItemClass == ItemClassContainer && dest.BagIndex() > -1) {
|
||||
if(i_src->GetContainer()->Size() > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(dest.IsEquipment() && !CanEquip(i_src, dest)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -130,7 +130,7 @@ namespace EQEmu
|
||||
void SetRace(int race);
|
||||
void SetClass(int class_);
|
||||
void SetDeity(int deity);
|
||||
void SetDataMode(InventoryDataModel *dm);
|
||||
void SetDataModel(InventoryDataModel *dm);
|
||||
|
||||
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
|
||||
bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
|
||||
|
||||
@ -30,10 +30,10 @@ namespace EQEmu
|
||||
virtual ~InventoryDataModel() { }
|
||||
|
||||
virtual void Begin() = 0;
|
||||
virtual void Commit() = 0;
|
||||
virtual bool Commit() = 0;
|
||||
virtual void Rollback() = 0;
|
||||
virtual bool Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) = 0;
|
||||
virtual bool Delete(const InventorySlot &slot) = 0;
|
||||
virtual void Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) = 0;
|
||||
virtual void Delete(const InventorySlot &slot) = 0;
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
|
||||
197
common/inventory_db_data_model.cpp
Normal file
197
common/inventory_db_data_model.cpp
Normal file
@ -0,0 +1,197 @@
|
||||
#include "inventory_db_data_model.h"
|
||||
#include "shareddb.h"
|
||||
#include "string_util.h"
|
||||
#include <list>
|
||||
#include <string>
|
||||
|
||||
enum DataEventTypes
|
||||
{
|
||||
DB_Insert,
|
||||
DB_Delete
|
||||
};
|
||||
|
||||
struct DataEvent
|
||||
{
|
||||
DataEventTypes evt;
|
||||
EQEmu::InventorySlot slot;
|
||||
std::shared_ptr<EQEmu::ItemInstance> inst;
|
||||
};
|
||||
|
||||
struct EQEmu::InventoryDatabaseDataModel::impl {
|
||||
SharedDatabase *db_;
|
||||
std::list<DataEvent> events_;
|
||||
uint32 char_id_;
|
||||
};
|
||||
|
||||
EQEmu::InventoryDatabaseDataModel::InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id) {
|
||||
impl_ = new impl;
|
||||
impl_->db_ = db;
|
||||
impl_->char_id_ = char_id;
|
||||
}
|
||||
|
||||
EQEmu::InventoryDatabaseDataModel::~InventoryDatabaseDataModel() {
|
||||
delete impl_;
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Begin() {
|
||||
impl_->db_->TransactionBegin();
|
||||
impl_->events_.clear();
|
||||
}
|
||||
|
||||
bool EQEmu::InventoryDatabaseDataModel::Commit() {
|
||||
std::string base_insert = "INSERT INTO character_inventory(id, type, slot, bag_index, aug_index, "
|
||||
"item_id, charges, color, attuned, custom_data, ornament_icon, ornament_idfile, ornament_hero_model"
|
||||
", tracking_id) VALUES";
|
||||
|
||||
std::string current_insert = base_insert;
|
||||
bool insert = false;
|
||||
for(auto iter : impl_->events_) {
|
||||
if(iter.evt == DB_Delete) {
|
||||
if(insert) {
|
||||
insert = false;
|
||||
|
||||
//commit the current_insert
|
||||
auto res = impl_->db_->QueryDatabase(current_insert);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
current_insert = base_insert;
|
||||
}
|
||||
|
||||
std::string current_delete;
|
||||
if(iter.slot.BagIndex() > -1) {
|
||||
if(iter.slot.AugIndex() > -1) {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u AND aug_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex(), iter.slot.AugIndex());
|
||||
}
|
||||
else {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND bag_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.BagIndex());
|
||||
}
|
||||
}
|
||||
else if(iter.slot.AugIndex() > -1) {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u AND aug_index=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot(), iter.slot.AugIndex());
|
||||
}
|
||||
else {
|
||||
current_delete = StringFormat("DELETE FROM character_inventory WHERE id=%u AND type=%u AND slot=%u",
|
||||
impl_->char_id_, iter.slot.Type(), iter.slot.Slot());
|
||||
}
|
||||
|
||||
auto res = impl_->db_->QueryDatabase(current_delete);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
} else {
|
||||
//insert
|
||||
if(!insert) {
|
||||
insert = true;
|
||||
} else {
|
||||
current_insert += ",";
|
||||
}
|
||||
|
||||
current_insert += StringFormat("(%u, %i, %i, %i, %i, %u, %i, %u, %u, '%s', %u, %u, %u, %llu)",
|
||||
impl_->char_id_,
|
||||
iter.slot.Type(),
|
||||
iter.slot.Slot(),
|
||||
iter.slot.BagIndex(),
|
||||
iter.slot.AugIndex(),
|
||||
iter.inst->GetBaseItem()->ID,
|
||||
iter.inst->GetCharges(),
|
||||
iter.inst->GetColor(),
|
||||
iter.inst->GetAttuned(),
|
||||
EscapeString(iter.inst->GetCustomData()).c_str(),
|
||||
iter.inst->GetOrnamentIcon(),
|
||||
iter.inst->GetOrnamentIDFile(),
|
||||
iter.inst->GetOrnamentHeroModel(),
|
||||
iter.inst->GetTrackingID());
|
||||
}
|
||||
}
|
||||
|
||||
if(insert) {
|
||||
insert = false;
|
||||
|
||||
//commit the current_insert
|
||||
auto res = impl_->db_->QueryDatabase(current_insert);
|
||||
if(!res.Success()) {
|
||||
Rollback();
|
||||
return false;
|
||||
}
|
||||
|
||||
current_insert = base_insert;
|
||||
}
|
||||
|
||||
impl_->db_->TransactionCommit();
|
||||
impl_->events_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Rollback() {
|
||||
impl_->db_->TransactionRollback();
|
||||
impl_->events_.clear();
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = inst;
|
||||
evt.slot = slot;
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
//insert current item
|
||||
if(slot.BagIndex() < 0 && slot.AugIndex() < 0) {
|
||||
//if bag put all bag contents in
|
||||
//if common put all augment contents in
|
||||
if(inst->GetBaseItem()->ItemClass == ItemClassContainer) {
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first);
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
|
||||
//if common put all augment contents in
|
||||
auto container = inst->GetContainer();
|
||||
auto iter = container->Begin();
|
||||
while(iter != container->End()) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Insert;
|
||||
evt.inst = iter->second;
|
||||
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, slot.BagIndex());
|
||||
impl_->events_.push_back(evt);
|
||||
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EQEmu::InventoryDatabaseDataModel::Delete(const InventorySlot &slot) {
|
||||
DataEvent evt;
|
||||
evt.evt = DB_Delete;
|
||||
evt.slot = slot;
|
||||
impl_->events_.push_back(evt);
|
||||
}
|
||||
45
common/inventory_db_data_model.h
Normal file
45
common/inventory_db_data_model.h
Normal file
@ -0,0 +1,45 @@
|
||||
/* EQEMu: Everquest Server Emulator
|
||||
Copyright (C) 2001-2015 EQEMu Development Team (http://eqemulator.net)
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; version 2 of the License.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY except by those people which sell it, which
|
||||
are required to give you total support for your newly bought product;
|
||||
without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef COMMON_INVENTORY_DB_DATA_MODEL_H
|
||||
#define COMMON_INVENTORY_DB_DATA_MODEL_H
|
||||
|
||||
#include "inventory_data_model.h"
|
||||
|
||||
class SharedDatabase;
|
||||
|
||||
namespace EQEmu
|
||||
{
|
||||
class InventoryDatabaseDataModel : public InventoryDataModel
|
||||
{
|
||||
public:
|
||||
InventoryDatabaseDataModel(SharedDatabase *db, uint32 char_id);
|
||||
virtual ~InventoryDatabaseDataModel();
|
||||
|
||||
virtual void Begin();
|
||||
virtual bool Commit();
|
||||
virtual void Rollback();
|
||||
virtual void Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
|
||||
virtual void Delete(const InventorySlot &slot);
|
||||
private:
|
||||
struct impl;
|
||||
impl *impl_;
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
#endif
|
||||
@ -30,10 +30,10 @@ namespace EQEmu
|
||||
virtual ~InventoryNullDataModel() { }
|
||||
|
||||
virtual void Begin() { printf("NDM: Begin\n"); }
|
||||
virtual void Commit() { printf("NDM: Commit\n"); }
|
||||
virtual bool Commit() { printf("NDM: Commit\n"); return true; }
|
||||
virtual void Rollback() { printf("NDM: Rollback\n"); }
|
||||
virtual bool Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) { printf("NDM: Insert %s %s\n", slot.ToString().c_str(), inst ? inst->GetBaseItem()->Name : "Null" ); return true; }
|
||||
virtual bool Delete(const InventorySlot &slot) { printf("NDM: Delete %s\n", slot.ToString().c_str()); return true; }
|
||||
virtual void Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) { printf("NDM: Insert %s %s\n", slot.ToString().c_str(), inst ? inst->GetBaseItem()->Name : "Null" ); }
|
||||
virtual void Delete(const InventorySlot &slot) { printf("NDM: Delete %s\n", slot.ToString().c_str()); }
|
||||
};
|
||||
} // EQEmu
|
||||
|
||||
|
||||
@ -188,6 +188,14 @@ void EQEmu::ItemInstance::SetCharges(const int16 charges) {
|
||||
impl_->charges_ = charges;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetColor() {
|
||||
return impl_->color_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetColor() const {
|
||||
return impl_->color_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetColor(const uint32 color) {
|
||||
impl_->color_ = color;
|
||||
}
|
||||
@ -204,6 +212,14 @@ void EQEmu::ItemInstance::SetAttuned(const bool attuned) {
|
||||
impl_->attuned_ = attuned;
|
||||
}
|
||||
|
||||
std::string EQEmu::ItemInstance::GetCustomData() {
|
||||
return impl_->custom_data_;
|
||||
}
|
||||
|
||||
std::string EQEmu::ItemInstance::GetCustomData() const {
|
||||
return impl_->custom_data_;
|
||||
}
|
||||
|
||||
void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) {
|
||||
//We need to actually set the custom data stuff based on this string
|
||||
impl_->custom_data_ = custom_data;
|
||||
@ -233,6 +249,14 @@ void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) {
|
||||
impl_->ornament_icon_ = ornament_icon;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() {
|
||||
return impl_->ornament_hero_model_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel() const {
|
||||
return impl_->ornament_hero_model_;
|
||||
}
|
||||
|
||||
uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) {
|
||||
uint32 hero_model = 0;
|
||||
if(impl_->ornament_hero_model_ > 0)
|
||||
|
||||
@ -49,12 +49,16 @@ namespace EQEmu
|
||||
int16 GetCharges() const;
|
||||
void SetCharges(const int16 charges);
|
||||
|
||||
uint32 GetColor();
|
||||
uint32 GetColor() const;
|
||||
void SetColor(const uint32 color);
|
||||
|
||||
bool GetAttuned();
|
||||
bool GetAttuned() const;
|
||||
void SetAttuned(const bool attuned);
|
||||
|
||||
std::string GetCustomData();
|
||||
std::string GetCustomData() const;
|
||||
void SetCustomData(const std::string &custom_data);
|
||||
|
||||
uint32 GetOrnamentIDFile();
|
||||
@ -65,6 +69,8 @@ namespace EQEmu
|
||||
uint32 GetOrnamentIcon() const;
|
||||
void SetOrnamentIcon(const uint32 ornament_icon);
|
||||
|
||||
uint32 GetOrnamentHeroModel();
|
||||
uint32 GetOrnamentHeroModel() const;
|
||||
uint32 GetOrnamentHeroModel(int material_slot);
|
||||
uint32 GetOrnamentHeroModel(int material_slot) const;
|
||||
void SetOrnamentHeroModel(const uint32 ornament_hero_model);
|
||||
|
||||
@ -47,6 +47,7 @@
|
||||
#include "../common/spdat.h"
|
||||
#include "../common/string_util.h"
|
||||
#include "../common/zone_numbers.h"
|
||||
#include "../common/inventory_db_data_model.h"
|
||||
#include "event_codes.h"
|
||||
#include "guild_mgr.h"
|
||||
#include "merc.h"
|
||||
@ -1289,6 +1290,7 @@ void Client::Handle_Connect_OP_ZoneEntry(const EQApplicationPacket *app)
|
||||
m_inventory.SetRace(GetBaseRace());
|
||||
m_inventory.SetClass(GetBaseClass());
|
||||
m_inventory.SetDeity(GetDeity());
|
||||
m_inventory.SetDataModel(new EQEmu::InventoryDatabaseDataModel(&database, CharacterID()));
|
||||
loaditems = database.GetInventory(cid, &m_inventory); /* Load Character Inventory */
|
||||
|
||||
/* Load AdventureStats */
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user