From ca278d029e5fec57bdca650dd72f150484ce77a8 Mon Sep 17 00:00:00 2001 From: KimLS Date: Sun, 22 Feb 2015 19:38:44 -0800 Subject: [PATCH] Fix for Memory Buffer stuff, have yet to compile so not sure if that's enough. Partial work on RoF inventory bulk send --- common/inventory.cpp | 19 +++++- common/inventory.h | 2 +- common/item_container.cpp | 14 ++++ common/item_container.h | 3 + common/item_data.h | 6 ++ common/memory_buffer.cpp | 23 ++++++- common/memory_buffer.h | 17 ++--- common/patches/rof2.cpp | 132 +++++++++++++++++++++---------------- tests/memory_buffer_test.h | 82 ++++++++++++++++++++++- zone/client_process.cpp | 9 +++ 10 files changed, 233 insertions(+), 74 deletions(-) diff --git a/common/inventory.cpp b/common/inventory.cpp index 96203fda3..05ae27690 100644 --- a/common/inventory.cpp +++ b/common/inventory.cpp @@ -89,10 +89,25 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptrcontainers_) { + bool v = iter.second.Serialize(buf, iter.first); + if(v && !value) { + value = true; + } + } + + return value; +} diff --git a/common/inventory.h b/common/inventory.h index b40253e48..27ace1ff5 100644 --- a/common/inventory.h +++ b/common/inventory.h @@ -61,7 +61,7 @@ namespace EQEmu bool Put(const InventorySlot &slot, std::shared_ptr inst); bool Swap(const InventorySlot &src, const InventorySlot &dest); - void Serialize(); + bool Serialize(MemoryBuffer &buf); private: struct impl; impl *impl_; diff --git a/common/item_container.cpp b/common/item_container.cpp index 38923a8cb..e84d193e3 100644 --- a/common/item_container.cpp +++ b/common/item_container.cpp @@ -56,3 +56,17 @@ bool EQEmu::ItemContainer::Delete(const int slot_id) { return true; } } + +bool EQEmu::ItemContainer::Serialize(MemoryBuffer &buf, int container_number) { + if(impl_->items.size() == 0) { + return false; + } + + for(auto &iter : impl_->items) { + buf.Write(container_number); + buf.Write(iter.first); + buf.Write(iter.second.get()); + } + + return true; +} \ No newline at end of file diff --git a/common/item_container.h b/common/item_container.h index 2847b940b..549611858 100644 --- a/common/item_container.h +++ b/common/item_container.h @@ -20,6 +20,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define COMMON_ITEM_CONTAINER_H #include "item_instance.h" +#include "memory_buffer.h" #include namespace EQEmu @@ -34,6 +35,8 @@ namespace EQEmu std::shared_ptr Get(const int slot_id); bool Put(const int slot_id, std::shared_ptr inst); bool Delete(const int slot_id); + + bool Serialize(MemoryBuffer &buf, int container_number); private: ItemContainer(const ItemContainer &other); ItemContainer& operator=(const ItemContainer &other); diff --git a/common/item_data.h b/common/item_data.h index e5a8fb395..0df9a86a0 100644 --- a/common/item_data.h +++ b/common/item_data.h @@ -69,6 +69,12 @@ struct InternalSerializedItem_Struct { const void * inst; }; +struct SerializedItemInstance_Struct { + int32 container_id; + int32 slot_id; + void *inst; +}; + // use EmuConstants::ITEM_COMMON_SIZE //#define MAX_AUGMENT_SLOTS 5 diff --git a/common/memory_buffer.cpp b/common/memory_buffer.cpp index cd10fe0c2..c8ebaf5b8 100644 --- a/common/memory_buffer.cpp +++ b/common/memory_buffer.cpp @@ -76,6 +76,25 @@ EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) { return *this; } +EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator+=(const MemoryBuffer &rhs) { + if(!rhs.buffer_) { + return *this; + } + + if(buffer_) { + size_t old_size = size_; + Resize(size_ + rhs.size_); + memcpy(&buffer_[old_size], rhs.buffer_, rhs.size_); + } else { + buffer_ = new uchar[rhs.capacity_]; + memcpy(buffer_, rhs.buffer_, rhs.capacity_); + size_ = rhs.size_; + capacity_ = rhs.capacity_; + } + + return *this; +} + EQEmu::MemoryBuffer::~MemoryBuffer() { Clear(); } uchar& EQEmu::MemoryBuffer::operator[](size_t pos) { @@ -112,7 +131,7 @@ size_t EQEmu::MemoryBuffer::Capacity() const { void EQEmu::MemoryBuffer::Resize(size_t sz) { if(!buffer_) { - size_t new_size = sz + 32; + size_t new_size = sz + 64; buffer_ = new uchar[new_size]; capacity_ = new_size; size_ = sz; @@ -143,6 +162,8 @@ void EQEmu::MemoryBuffer::Clear() { size_ = 0; capacity_ = 0; + write_pos_ = 0; + read_pos_ = 0; } void EQEmu::MemoryBuffer::Zero() { diff --git a/common/memory_buffer.h b/common/memory_buffer.h index beec6b809..26a5897df 100644 --- a/common/memory_buffer.h +++ b/common/memory_buffer.h @@ -35,6 +35,8 @@ namespace EQEmu MemoryBuffer(MemoryBuffer &&other); MemoryBuffer& operator=(const MemoryBuffer &other); MemoryBuffer& operator=(MemoryBuffer &&other); + MemoryBuffer& operator+=(const MemoryBuffer &rhs); + friend MemoryBuffer operator+(MemoryBuffer lhs, const MemoryBuffer& rhs) { return lhs += rhs; } ~MemoryBuffer(); uchar& operator[](size_t pos); @@ -78,27 +80,18 @@ namespace EQEmu return temp; } - template<> - void Write(std::string val) { + void Write(const std::string &val) { Write(val.c_str(), val.length()); Write((uint8)0); } - template<> - void Write(const std::string &val) { - Write(val.c_str(), val.length()); - Write((uint8)0); - } - - template<> - void Write(const char *val) { + void Write(const char *val) { size_t len = strlen(val); Write(val, len); Write((uint8)0); } - template<> - std::string Read() { + std::string ReadString() { std::string ret; size_t len = strlen((const char*)&buffer_[read_pos_]); ret.resize(len); diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 63a015ab7..3126f13ce 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -12,6 +12,7 @@ #include "../item.h" #include "rof2_structs.h" #include "../rulesys.h" +#include "../memory_buffer.h" #include #include @@ -598,71 +599,90 @@ namespace RoF2 { //consume the packet EQApplicationPacket *in = *p; - *p = nullptr; - if (in->size == 0) { - - in->size = 4; - in->pBuffer = new uchar[in->size]; - - *((uint32 *)in->pBuffer) = 0; - - dest->FastQueuePacket(&in, ack_req); - return; - } - - //store away the emu struct - unsigned char *__emu_buffer = in->pBuffer; - - int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); - - if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) { + in->SetReadPosition(0); + size_t entry_size = sizeof(int32) * 2 + sizeof(void*); + size_t entries = in->size / entry_size; + if(entries == 0 || in->size % 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(InternalSerializedItem_Struct)); - + opcodes->EmuToName(in->GetOpcode()), in->size, entry_size); delete in; - return; } - InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + //SerializedItemInstance_Struct *sis = (SerializedItemInstance_Struct*)in->pBuffer; + //EQEmu::MemoryBuffer packet_data; + //packet_data.Write(entries); + // + //for(size_t i = 0; i < entries; ++i) { + // //SerializeItem((const EQEmu::ItemInstance*) + // //char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); + //} - in->pBuffer = new uchar[4]; - *(uint32 *)in->pBuffer = ItemCount; - in->size = 4; - - for (int r = 0; r < ItemCount; r++, eq++) { - - uint32 Length = 0; - - char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); - - if (Serialized) { - - uchar *OldBuffer = in->pBuffer; - in->pBuffer = new uchar[in->size + Length]; - memcpy(in->pBuffer, OldBuffer, in->size); - - safe_delete_array(OldBuffer); - - memcpy(in->pBuffer + in->size, Serialized, Length); - in->size += Length; - - safe_delete_array(Serialized); - } - else { - Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - } - } - - delete[] __emu_buffer; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); - //Log.Hex(Logs::Netcode, in->pBuffer, in->size); - - dest->FastQueuePacket(&in, ack_req); + //if (in->size == 0) { + // + // in->size = 4; + // in->pBuffer = new uchar[in->size]; + // + // *((uint32 *)in->pBuffer) = 0; + // + // dest->FastQueuePacket(&in, ack_req); + // return; + //} + // + ////store away the emu struct + //unsigned char *__emu_buffer = in->pBuffer; + // + //int ItemCount = in->size / sizeof(InternalSerializedItem_Struct); + // + //if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 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(InternalSerializedItem_Struct)); + // + // delete in; + // + // return; + //} + // + //InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer; + // + //in->pBuffer = new uchar[4]; + //*(uint32 *)in->pBuffer = ItemCount; + //in->size = 4; + // + //for (int r = 0; r < ItemCount; r++, eq++) { + // + // uint32 Length = 0; + // + // char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory); + // + // if (Serialized) { + // + // uchar *OldBuffer = in->pBuffer; + // in->pBuffer = new uchar[in->size + Length]; + // memcpy(in->pBuffer, OldBuffer, in->size); + // + // safe_delete_array(OldBuffer); + // + // memcpy(in->pBuffer + in->size, Serialized, Length); + // in->size += Length; + // + // safe_delete_array(Serialized); + // } + // else { + // Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); + // } + //} + // + //delete[] __emu_buffer; + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client"); + ////Log.Hex(Logs::Netcode, in->pBuffer, in->size); + // + //dest->FastQueuePacket(&in, ack_req); } ENCODE(OP_ClickObjectAction) diff --git a/tests/memory_buffer_test.h b/tests/memory_buffer_test.h index 366795bab..db5df217e 100644 --- a/tests/memory_buffer_test.h +++ b/tests/memory_buffer_test.h @@ -35,6 +35,7 @@ public: TEST_ADD(MemoryBufferTest::MoveTest); TEST_ADD(MemoryBufferTest::ZeroTest); TEST_ADD(MemoryBufferTest::ClearTest); + TEST_ADD(MemoryBufferTest::AddTest) } ~MemoryBufferTest() { @@ -93,8 +94,8 @@ private: uint16 b = mb.Read(); uint32 c = mb.Read(); uint64 d = mb.Read(); - std::string s1 = mb.Read(); - std::string s2 = mb.Read(); + std::string s1 = mb.ReadString(); + std::string s2 = mb.ReadString(); TEST_ASSERT(a == 0); TEST_ASSERT(b == 5); @@ -504,6 +505,83 @@ private: TEST_ASSERT(data == nullptr); } + void AddTest() + { + EQEmu::MemoryBuffer mb2; + EQEmu::MemoryBuffer mb3; + + mb2 += mb3; + + TEST_ASSERT(!mb2); + TEST_ASSERT(mb2.Size() == 0); + + mb2.Write("test1"); + mb2.Write("test2"); + + mb2 += mb3; + TEST_ASSERT(mb2); + TEST_ASSERT(mb2.Size() == 12); + + uchar *data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + + mb3 += mb2; + TEST_ASSERT(mb3); + TEST_ASSERT(mb3.Size() == 12); + + data = (uchar*)mb3; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + + mb2.Clear(); + mb3.Clear(); + + mb2.Write("test1"); + mb3.Write("test2"); + + mb2 += mb3; + TEST_ASSERT(mb2); + TEST_ASSERT(mb2.Size() == 12); + + data = (uchar*)mb2; + TEST_ASSERT(data != nullptr); + TEST_ASSERT(data[0] == 't'); + TEST_ASSERT(data[1] == 'e'); + TEST_ASSERT(data[2] == 's'); + TEST_ASSERT(data[3] == 't'); + TEST_ASSERT(data[4] == '1'); + TEST_ASSERT(data[5] == 0); + TEST_ASSERT(data[6] == 't'); + TEST_ASSERT(data[7] == 'e'); + TEST_ASSERT(data[8] == 's'); + TEST_ASSERT(data[9] == 't'); + TEST_ASSERT(data[10] == '2'); + TEST_ASSERT(data[11] == 0); + } + EQEmu::MemoryBuffer mb; }; diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 938bfbc87..5adf4bb6f 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -815,6 +815,15 @@ void Client::OnDisconnect(bool hard_disconnect) { } void Client::BulkSendInventoryItems() { + EQEmu::MemoryBuffer items; + if(!m_inventory.Serialize(items)) { + return; + } + + EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, items.Size()); + memcpy(outapp->pBuffer, items, items.Size()); + + //int16 slot_id = 0; // //// LINKDEAD TRADE ITEMS