mirror of
https://github.com/EQEmu/Server.git
synced 2026-05-17 03:08:26 +00:00
Basic item summoning, fix for saving not working 100 pct, deletion works, cursor queue should work too.
This commit is contained in:
+168
-12
@@ -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_) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user