Basic item summoning, fix for saving not working 100 pct, deletion works, cursor queue should work too.

This commit is contained in:
KimLS
2015-03-05 18:03:37 -08:00
parent 316aa5ef73
commit dda8ae4803
14 changed files with 459 additions and 108 deletions
+168 -12
View File
@@ -22,6 +22,7 @@
#include "data_verification.h"
#include "string_util.h"
#include <map>
#include <queue>
bool EQEmu::InventorySlot::IsValid() const {
if(type_ == InvTypePersonal && EQEmu::ValueWithin(slot_, PersonalSlotCharm, PersonalSlotCursor)) {
@@ -225,7 +226,28 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
return true;
}
if(!src.IsValid() || !dest.IsValid()) {
if(!src.IsValid()) {
return false;
}
if(src.Type() == InvTypeCursorBuffer || dest.Type() == InvTypeCursorBuffer) {
return true;
}
if(dest.IsDelete()) {
impl_->data_model_->Begin();
bool v = _destroy(src);
if(v) {
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
if(!dest.IsValid()) {
return false;
}
@@ -252,17 +274,6 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
}
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()) {
//move # charges from src to dest
@@ -356,6 +367,109 @@ bool EQEmu::Inventory::Swap(const InventorySlot &src, const InventorySlot &dest,
return true;
}
bool EQEmu::Inventory::Summon(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) {
if(!inst)
return false;
if(CheckLoreConflict(inst->GetBaseItem())) {
return false;
}
auto cur = Get(slot);
if(cur) {
if(slot.IsCursor()) {
PushToCursorBuffer(inst);
}
return false;
}
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
} else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PushToCursorBuffer(std::shared_ptr<ItemInstance> inst) {
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
impl_->containers_.insert(std::pair<int, ItemContainer>(InvTypeCursorBuffer, ItemContainer()));
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top + 1);
impl_->data_model_->Begin();
bool v = Put(slot, inst);
if(v) {
impl_->data_model_->Insert(slot, inst);
impl_->data_model_->Commit();
}
else {
impl_->data_model_->Rollback();
}
return v;
}
bool EQEmu::Inventory::PopFromCursorBuffer() {
InventorySlot cursor(InvTypePersonal, PersonalSlotCursor);
auto inst = Get(cursor);
if(inst) {
return false;
}
if(impl_->containers_.count(InvTypeCursorBuffer) == 0) {
return false;
}
int32 top = 0;
auto &container = impl_->containers_[InvTypeCursorBuffer];
auto iter = container.Begin();
while(iter != container.End()) {
top = iter->first;
++iter;
}
InventorySlot slot(InvTypeCursorBuffer, top);
inst = Get(slot);
if(inst) {
impl_->data_model_->Begin();
bool v = _destroy(slot);
impl_->data_model_->Delete(slot);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
v = Put(cursor, inst);
impl_->data_model_->Insert(cursor, inst);
if(!v) {
impl_->data_model_->Rollback();
return false;
}
impl_->data_model_->Commit();
return true;
}
return false;
}
int EQEmu::Inventory::CalcMaterialFromSlot(const InventorySlot &slot) {
if(slot.Type() != 0)
return _MaterialInvalid;
@@ -441,17 +555,59 @@ bool EQEmu::Inventory::CanEquip(std::shared_ptr<EQEmu::ItemInstance> inst, const
return false;
}
//todo: check deity
if(!item->IsEquipable(impl_->race_, impl_->class_)) {
return false;
}
//Checking augments
auto iter = inst->GetContainer()->Begin();
auto end = inst->GetContainer()->End();
while(iter != end) {
if(!CanEquip(iter->second, InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first))) {
return false;
}
++iter;
}
return true;
}
bool EQEmu::Inventory::CheckLoreConflict(const ItemData *item) {
if(!item)
return false;
if(!item->LoreFlag)
return false;
if(item->LoreGroup == 0)
return false;
if(item->LoreGroup == 0xFFFFFFFF) {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItem(item->ID)) {
return true;
}
}
}
else {
//look everywhere except shared bank
for(auto &container : impl_->containers_) {
if(container.first != InvTypeSharedBank && container.second.HasItemByLoreGroup(item->LoreGroup)) {
return true;
}
}
}
return false;
}
bool EQEmu::Inventory::Serialize(MemoryBuffer &buf) {
buf.SetWritePosition(0);
buf.SetReadPosition(0);
buf.Resize(0);
buf.Write<int32>(105);
bool value = false;
for(auto &iter : impl_->containers_) {
+4
View File
@@ -135,11 +135,15 @@ namespace EQEmu
std::shared_ptr<ItemInstance> Get(const InventorySlot &slot);
bool Put(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges);
bool Summon(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst);
bool PushToCursorBuffer(std::shared_ptr<ItemInstance> inst);
bool PopFromCursorBuffer();
//utility
static int CalcMaterialFromSlot(const InventorySlot &slot);
static InventorySlot CalcSlotFromMaterial(int material);
bool CanEquip(std::shared_ptr<EQEmu::ItemInstance> inst, const EQEmu::InventorySlot &slot);
bool CheckLoreConflict(const ItemData *item);
bool Serialize(MemoryBuffer &buf);
//testing
+20 -5
View File
@@ -153,9 +153,23 @@ void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, std::s
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, -1);
impl_->events_.push_back(evt);
//do augments here
if(evt.inst->GetBaseItem()->ItemClass == ItemClassCommon) {
auto inst_container = evt.inst->GetContainer();
auto inst_iter = inst_container->Begin();
while(inst_iter != inst_container->End()) {
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = inst_iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, inst_iter->first);
impl_->events_.push_back(evt);
++inst_iter;
}
}
++iter;
}
}
@@ -166,14 +180,15 @@ void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, std::s
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first);
evt.slot = InventorySlot(slot.Type(), slot.Slot(), -1, iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
}
else if(inst->GetBaseItem()->ItemClass == ItemClassCommon) {
else if(slot.AugIndex() < 0 && inst->GetBaseItem()->ItemClass == ItemClassCommon) {
//bag item that can have augs
//if common put all augment contents in
auto container = inst->GetContainer();
auto iter = container->Begin();
@@ -181,9 +196,9 @@ void EQEmu::InventoryDatabaseDataModel::Insert(const InventorySlot &slot, std::s
DataEvent evt;
evt.evt = DB_Insert;
evt.inst = iter->second;
evt.slot = InventorySlot(slot.Type(), slot.Slot(), iter->first, slot.BagIndex());
evt.slot = InventorySlot(slot.Type(), slot.Slot(), slot.BagIndex(), iter->first);
impl_->events_.push_back(evt);
++iter;
}
}
+5 -5
View File
@@ -29,11 +29,11 @@ namespace EQEmu
InventoryNullDataModel() { }
virtual ~InventoryNullDataModel() { }
virtual void Begin() { printf("NDM: Begin\n"); }
virtual bool Commit() { printf("NDM: Commit\n"); return true; }
virtual void Rollback() { printf("NDM: Rollback\n"); }
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()); }
virtual void Begin() { }
virtual bool Commit() { return true; }
virtual void Rollback() { }
virtual void Insert(const InventorySlot &slot, std::shared_ptr<ItemInstance> inst) { }
virtual void Delete(const InventorySlot &slot) { }
};
} // EQEmu
+23
View File
@@ -65,6 +65,29 @@ bool EQEmu::ItemContainer::Put(const int slot_id, std::shared_ptr<ItemInstance>
return false;
}
bool EQEmu::ItemContainer::HasItem(uint32 item_id) {
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->ID == item_id) {
return true;
}
}
return false;
}
bool EQEmu::ItemContainer::HasItemByLoreGroup(uint32 loregroup) {
if(loregroup == 0xFFFFFFFF)
return false;
for(auto &item : impl_->items_) {
if(item.second->GetBaseItem()->LoreGroup == loregroup) {
return true;
}
}
return false;
}
uint32 EQEmu::ItemContainer::Size() {
return (uint32)impl_->items_.size();
}
+5
View File
@@ -42,6 +42,11 @@ namespace EQEmu
std::shared_ptr<ItemInstance> Get(const int slot_id);
bool Put(const int slot_id, std::shared_ptr<ItemInstance> inst);
bool Delete(const int slot_id);
//Utility
bool HasItem(uint32 item_id);
bool HasItemByLoreGroup(uint32 loregroup);
uint32 Size();
uint32 Size() const;
@@ -9,6 +9,8 @@ bool EQEmu::ItemContainerDefaultSerialization::Serialize(MemoryBuffer &buf, cons
for(auto &iter : items) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
@@ -10,6 +10,8 @@ bool EQEmu::ItemContainerPersonalSerialization::Serialize(MemoryBuffer &buf, con
if(iter.first < 33) {
buf.Write<int32>(container_number);
buf.Write<int32>(iter.first);
buf.Write<int32>(-1);
buf.Write<int32>(-1);
buf.Write<void*>(iter.second.get());
ret = true;
}
+2
View File
@@ -72,6 +72,8 @@ struct InternalSerializedItem_Struct {
struct SerializedItemInstance_Struct {
int32 container_id;
int32 slot_id;
int32 bag_id;
int32 aug_id;
void *inst;
};
+39 -31
View File
@@ -602,18 +602,18 @@ namespace RoF2
EQApplicationPacket *in = *p;
*p = nullptr;
size_t entry_size = sizeof(int32) * 2 + sizeof(void*);
size_t entries = in->size / entry_size;
size_t entry_size = sizeof(SerializedItemInstance_Struct);
size_t entries = (in->size - sizeof(int32)) / entry_size;
if(entries == 0 || in->size % entry_size != 0) {
if(entries == 0 || (in->size - sizeof(int32)) % entry_size != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), in->size, entry_size);
opcodes->EmuToName(in->GetOpcode()), (in->size - sizeof(int32)), entry_size);
delete in;
return;
}
unsigned char *__emu_buffer = in->pBuffer;
SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)__emu_buffer;
SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)(__emu_buffer + sizeof(int32));
EQEmu::MemoryBuffer packet_data;
packet_data.Write<uint32>(entries);
@@ -1490,33 +1490,41 @@ namespace RoF2
ENCODE(OP_ItemPacket)
{
delete *p;
EQApplicationPacket *in = *p;
*p = nullptr;
////consume the packet
//EQApplicationPacket *in = *p;
//*p = nullptr;
//
//unsigned char *__emu_buffer = in->pBuffer;
//ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
//InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
//
//uint32 length;
//char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType);
//
//if (!serialized) {
// Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
// delete in;
// return;
//}
//in->size = length + 4;
//in->pBuffer = new unsigned char[in->size];
//ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
//new_item_pkt->PacketType = old_item_pkt->PacketType;
//memcpy(new_item_pkt->SerializedItem, serialized, length);
//
//delete[] __emu_buffer;
//safe_delete_array(serialized);
//dest->FastQueuePacket(&in, ack_req);
size_t entry_size = sizeof(SerializedItemInstance_Struct);
size_t entries = (in->size - sizeof(int32)) / entry_size;
if(entries == 0 || entries > 1 || (in->size - sizeof(int32)) % entry_size != 0) {
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
opcodes->EmuToName(in->GetOpcode()), (in->size - sizeof(int32)), entry_size);
delete in;
return;
}
unsigned char *__emu_buffer = in->pBuffer;
int32 *packet_type = (int32*)(__emu_buffer);
SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)(__emu_buffer + sizeof(int32));
EQEmu::MemoryBuffer packet_data;
packet_data.Write<int32>(*packet_type);
EQEmu::ItemInstance *inst = (EQEmu::ItemInstance*)sis->inst;
if(!inst) {
delete in;
return;
}
SerializeItem(packet_data, inst, sis->container_id, sis->slot_id, sis->bag_id, sis->slot_id);
in->pBuffer = new uchar[packet_data.Size()];
in->size = packet_data.Size();
memcpy(in->pBuffer, packet_data, in->size);
delete[] __emu_buffer;
dest->FastQueuePacket(&in, ack_req);
}
ENCODE(OP_ItemVerifyReply)