mirror of
https://github.com/EQEmu/Server.git
synced 2026-03-27 18:52:27 +00:00
Fix for swapping a stack with another item that is not of the same stack size. Added some console visualization for testing and added basics of data modeling for inventory, saving soon.
This commit is contained in:
parent
abc5ddc5f8
commit
972d3d8874
@ -142,6 +142,8 @@ SET(common_headers
|
|||||||
guild_base.h
|
guild_base.h
|
||||||
guilds.h
|
guilds.h
|
||||||
inventory.h
|
inventory.h
|
||||||
|
inventory_data_model.h
|
||||||
|
inventory_null_data_model.h
|
||||||
ipc_mutex.h
|
ipc_mutex.h
|
||||||
item.h
|
item.h
|
||||||
item_container.h
|
item_container.h
|
||||||
|
|||||||
@ -17,8 +17,9 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "inventory.h"
|
#include "inventory.h"
|
||||||
#include "data_verification.h"
|
#include "inventory_null_data_model.h"
|
||||||
#include "item_container_personal_serialization.h"
|
#include "item_container_personal_serialization.h"
|
||||||
|
#include "data_verification.h"
|
||||||
#include "string_util.h"
|
#include "string_util.h"
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@ -123,6 +124,7 @@ struct EQEmu::Inventory::impl
|
|||||||
int race_;
|
int race_;
|
||||||
int class_;
|
int class_;
|
||||||
int deity_;
|
int deity_;
|
||||||
|
std::unique_ptr<InventoryDataModel> data_model_;
|
||||||
};
|
};
|
||||||
|
|
||||||
EQEmu::Inventory::Inventory(int race, int class_, int deity) {
|
EQEmu::Inventory::Inventory(int race, int class_, int deity) {
|
||||||
@ -130,6 +132,7 @@ EQEmu::Inventory::Inventory(int race, int class_, int deity) {
|
|||||||
impl_->race_ = race;
|
impl_->race_ = race;
|
||||||
impl_->class_ = class_;
|
impl_->class_ = class_;
|
||||||
impl_->deity_ = deity;
|
impl_->deity_ = deity;
|
||||||
|
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(new InventoryNullDataModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
EQEmu::Inventory::~Inventory() {
|
EQEmu::Inventory::~Inventory() {
|
||||||
@ -148,6 +151,10 @@ void EQEmu::Inventory::SetDeity(int deity) {
|
|||||||
impl_->deity_ = deity;
|
impl_->deity_ = deity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQEmu::Inventory::SetDataMode(InventoryDataModel *dm) {
|
||||||
|
impl_->data_model_ = std::unique_ptr<InventoryDataModel>(dm);
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<EQEmu::ItemInstance> EQEmu::Inventory::Get(const InventorySlot &slot) {
|
std::shared_ptr<EQEmu::ItemInstance> EQEmu::Inventory::Get(const InventorySlot &slot) {
|
||||||
auto iter = impl_->containers_.find(slot.Type());
|
auto iter = impl_->containers_.find(slot.Type());
|
||||||
if(iter != impl_->containers_.end()) {
|
if(iter != impl_->containers_.end()) {
|
||||||
@ -218,10 +225,6 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dest.IsDelete()) {
|
|
||||||
return _destroy(src);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!src.IsValid() || !dest.IsValid()) {
|
if(!src.IsValid() || !dest.IsValid()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -242,6 +245,18 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_->data_model_->Begin();
|
||||||
|
if(dest.IsDelete()) {
|
||||||
|
bool v = _destroy(src);
|
||||||
|
if(v) {
|
||||||
|
impl_->data_model_->Commit();
|
||||||
|
} else {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
if(i_src->IsStackable()) {
|
if(i_src->IsStackable()) {
|
||||||
//move # charges from src to dest
|
//move # charges from src to dest
|
||||||
|
|
||||||
@ -252,31 +267,46 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
|
|||||||
|
|
||||||
//src needs to have that many charges
|
//src needs to have that many charges
|
||||||
if(i_src->GetCharges() < charges) {
|
if(i_src->GetCharges() < charges) {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//if dest exists it needs to not only be the same item id but also be able to hold enough charges
|
//if dest exists it needs to not only be the same item id but also be able to hold enough charges to combine
|
||||||
|
//we can also swap if src id != dest id
|
||||||
if(i_dest) {
|
if(i_dest) {
|
||||||
uint32 src_id = i_src->GetBaseItem()->ID;
|
uint32 src_id = i_src->GetBaseItem()->ID;
|
||||||
uint32 dest_id = i_dest->GetBaseItem()->ID;
|
uint32 dest_id = i_dest->GetBaseItem()->ID;
|
||||||
if(src_id != dest_id) {
|
if(src_id != dest_id) {
|
||||||
return false;
|
bool v = _swap(src, dest);
|
||||||
|
if(v) {
|
||||||
|
impl_->data_model_->Commit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges();
|
int charges_avail = i_dest->GetBaseItem()->StackSize - i_dest->GetCharges();
|
||||||
if(charges_avail < charges) {
|
if(charges_avail < charges) {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i_src->GetCharges() == charges) {
|
if(i_src->GetCharges() == charges) {
|
||||||
if(!_destroy(src)) {
|
if(!_destroy(src)) {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
i_src->SetCharges(i_src->GetCharges() - charges);
|
i_src->SetCharges(i_src->GetCharges() - charges);
|
||||||
|
impl_->data_model_->Insert(src, i_src);
|
||||||
}
|
}
|
||||||
|
|
||||||
i_dest->SetCharges(i_dest->GetCharges() + charges);
|
i_dest->SetCharges(i_dest->GetCharges() + charges);
|
||||||
|
impl_->data_model_->Insert(dest, i_dest);
|
||||||
|
impl_->data_model_->Commit();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
//if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest
|
//if dest does not exist and src charges > # charges then we need to create a new item with # charges in dest
|
||||||
@ -284,19 +314,39 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
|
|||||||
if(i_src->GetCharges() > charges) {
|
if(i_src->GetCharges() > charges) {
|
||||||
auto split = i_src->Split(charges);
|
auto split = i_src->Split(charges);
|
||||||
if(!split) {
|
if(!split) {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Put(dest, split);
|
Put(dest, split);
|
||||||
|
impl_->data_model_->Insert(src, i_src);
|
||||||
|
impl_->data_model_->Insert(dest, split);
|
||||||
|
impl_->data_model_->Commit();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return _swap(src, dest);
|
bool v = _swap(src, dest);
|
||||||
|
if(v) {
|
||||||
|
impl_->data_model_->Commit();
|
||||||
|
} else {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return _swap(src, dest);
|
bool v = _swap(src, dest);
|
||||||
|
if(v) {
|
||||||
|
impl_->data_model_->Commit();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
impl_->data_model_->Rollback();
|
||||||
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_->data_model_->Commit();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -408,6 +458,16 @@ bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQEmu::Inventory::Interrogate() {
|
||||||
|
printf("Inventory:\n");
|
||||||
|
printf("Class: %u, Race: %u, Deity: %u\n", impl_->class_, impl_->race_, impl_->deity_);
|
||||||
|
for(auto &iter : impl_->containers_) {
|
||||||
|
printf("Container: %u\n", iter.first);
|
||||||
|
iter.second.Interrogate(1);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) {
|
bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest) {
|
||||||
auto src_i = Get(src);
|
auto src_i = Get(src);
|
||||||
auto dest_i = Get(dest);
|
auto dest_i = Get(dest);
|
||||||
@ -423,12 +483,14 @@ bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl_->data_model_->Insert(src, dest_i);
|
||||||
if(!Put(src, dest_i)) {
|
if(!Put(src, dest_i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(src_i) {
|
if(src_i) {
|
||||||
|
impl_->data_model_->Insert(dest, src_i);
|
||||||
if(!Put(dest, src_i)) {
|
if(!Put(dest, src_i)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -438,5 +500,7 @@ bool EQEmu::Inventory::_swap(const InventorySlot &src, const InventorySlot &dest
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EQEmu::Inventory::_destroy(const InventorySlot &slot) {
|
bool EQEmu::Inventory::_destroy(const InventorySlot &slot) {
|
||||||
return Put(slot, std::shared_ptr<EQEmu::ItemInstance>(nullptr));
|
bool v = Put(slot, std::shared_ptr<EQEmu::ItemInstance>(nullptr));
|
||||||
|
impl_->data_model_->Delete(slot);
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -120,6 +120,7 @@ namespace EQEmu
|
|||||||
lhs.AugIndex() == rhs.AugIndex(); }
|
lhs.AugIndex() == rhs.AugIndex(); }
|
||||||
inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); }
|
inline bool operator!=(const InventorySlot &lhs, const InventorySlot &rhs) { return !(lhs == rhs); }
|
||||||
|
|
||||||
|
class InventoryDataModel;
|
||||||
class Inventory
|
class Inventory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -129,6 +130,7 @@ namespace EQEmu
|
|||||||
void SetRace(int race);
|
void SetRace(int race);
|
||||||
void SetClass(int class_);
|
void SetClass(int class_);
|
||||||
void SetDeity(int deity);
|
void SetDeity(int deity);
|
||||||
|
void SetDataMode(InventoryDataModel *dm);
|
||||||
|
|
||||||
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
|
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
|
||||||
bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
|
bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
|
||||||
@ -139,6 +141,9 @@ namespace EQEmu
|
|||||||
static InventorySlot CalcSlotFromMaterial(int material);
|
static InventorySlot CalcSlotFromMaterial(int material);
|
||||||
bool CanEquip(std::shared_ptr<EQEmu::ItemInstance> inst, const EQEmu::InventorySlot &slot);
|
bool CanEquip(std::shared_ptr<EQEmu::ItemInstance> inst, const EQEmu::InventorySlot &slot);
|
||||||
bool Serialize(MemoryBuffer &buf);
|
bool Serialize(MemoryBuffer &buf);
|
||||||
|
|
||||||
|
//testing
|
||||||
|
void Interrogate();
|
||||||
private:
|
private:
|
||||||
bool _swap(const InventorySlot &src, const InventorySlot &dest);
|
bool _swap(const InventorySlot &src, const InventorySlot &dest);
|
||||||
bool _destroy(const InventorySlot &slot);
|
bool _destroy(const InventorySlot &slot);
|
||||||
|
|||||||
40
common/inventory_data_model.h
Normal file
40
common/inventory_data_model.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* 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_DATA_MODEL_H
|
||||||
|
#define COMMON_INVENTORY_DATA_MODEL_H
|
||||||
|
|
||||||
|
#include "inventory.h"
|
||||||
|
|
||||||
|
namespace EQEmu
|
||||||
|
{
|
||||||
|
class InventoryDataModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InventoryDataModel() { }
|
||||||
|
virtual ~InventoryDataModel() { }
|
||||||
|
|
||||||
|
virtual void Begin() = 0;
|
||||||
|
virtual void 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;
|
||||||
|
};
|
||||||
|
} // EQEmu
|
||||||
|
|
||||||
|
#endif
|
||||||
40
common/inventory_null_data_model.h
Normal file
40
common/inventory_null_data_model.h
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
/* 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_NULL_DATA_MODEL_H
|
||||||
|
#define COMMON_INVENTORY_NULL_DATA_MODEL_H
|
||||||
|
|
||||||
|
#include "inventory_data_model.h"
|
||||||
|
|
||||||
|
namespace EQEmu
|
||||||
|
{
|
||||||
|
class InventoryNullDataModel : public InventoryDataModel
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
InventoryNullDataModel() { }
|
||||||
|
virtual ~InventoryNullDataModel() { }
|
||||||
|
|
||||||
|
virtual void Begin() { printf("NDM: Begin\n"); }
|
||||||
|
virtual void Commit() { printf("NDM: Commit\n"); }
|
||||||
|
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; }
|
||||||
|
};
|
||||||
|
} // EQEmu
|
||||||
|
|
||||||
|
#endif
|
||||||
@ -98,3 +98,15 @@ EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::Begin() {
|
|||||||
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() {
|
EQEmu::ItemContainer::ItemContainerIter EQEmu::ItemContainer::End() {
|
||||||
return impl_->items_.end();
|
return impl_->items_.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQEmu::ItemContainer::Interrogate(int level) {
|
||||||
|
char buffer[16] = { 0 };
|
||||||
|
for(int i = 0; i < level; ++i) {
|
||||||
|
buffer[i] = '\t';
|
||||||
|
}
|
||||||
|
|
||||||
|
for(auto &iter : impl_->items_) {
|
||||||
|
printf("%s%u: (%u)%s (%u)\n", buffer, iter.first, iter.second->GetBaseItem()->ID, iter.second->GetBaseItem()->Name, iter.second->GetCharges());
|
||||||
|
iter.second->Interrogate(level + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -49,6 +49,9 @@ namespace EQEmu
|
|||||||
bool Serialize(MemoryBuffer &buf, int container_number);
|
bool Serialize(MemoryBuffer &buf, int container_number);
|
||||||
ItemContainerIter Begin();
|
ItemContainerIter Begin();
|
||||||
ItemContainerIter End();
|
ItemContainerIter End();
|
||||||
|
|
||||||
|
//testing
|
||||||
|
void Interrogate(int level);
|
||||||
protected:
|
protected:
|
||||||
struct impl;
|
struct impl;
|
||||||
impl *impl_;
|
impl *impl_;
|
||||||
|
|||||||
@ -360,3 +360,6 @@ EQEmu::ItemContainer *EQEmu::ItemInstance::GetContainer() {
|
|||||||
return &(impl_->contents_);
|
return &(impl_->contents_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EQEmu::ItemInstance::Interrogate(int level) {
|
||||||
|
impl_->contents_.Interrogate(level);
|
||||||
|
}
|
||||||
|
|||||||
@ -105,6 +105,8 @@ namespace EQEmu
|
|||||||
//Internal state
|
//Internal state
|
||||||
//Used for low level operations such as encode/decode
|
//Used for low level operations such as encode/decode
|
||||||
ItemContainer *GetContainer();
|
ItemContainer *GetContainer();
|
||||||
|
|
||||||
|
void Interrogate(int level);
|
||||||
private:
|
private:
|
||||||
struct impl;
|
struct impl;
|
||||||
impl *impl_;
|
impl *impl_;
|
||||||
|
|||||||
@ -3139,8 +3139,11 @@ bool Client::SwapItem(const EQEmu::InventorySlot &src, const EQEmu::InventorySlo
|
|||||||
|
|
||||||
if(res) {
|
if(res) {
|
||||||
Message(0, "Swap success\n");
|
Message(0, "Swap success\n");
|
||||||
|
m_inventory.Interrogate();
|
||||||
} else {
|
} else {
|
||||||
Message(0, "Swap failure!\n");
|
Message(0, "Swap failure!\n");
|
||||||
|
//should kick the player here...
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto_attack && res && recalc_weapon_speed) {
|
if(auto_attack && res && recalc_weapon_speed) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user