diff --git a/common/item.h b/common/item.h index 11e1ad151..7d60afdac 100644 --- a/common/item.h +++ b/common/item.h @@ -31,9 +31,11 @@ class EvolveInfo; // Stores information about an evolving item family #include "../common/timer.h" #include "../common/bodytypes.h" +#include "string_util.h" + #include #include -#include +//#include namespace ItemField @@ -413,7 +415,7 @@ public: uint32 GetKillsNeeded(uint8 currentlevel); std::string Serialize(int16 slot_id) const { InternalSerializedItem_Struct s; s.slot_id = slot_id; s.inst = (const void*)this; std::string ser; ser.assign((char*)&s, sizeof(InternalSerializedItem_Struct)); return ser; } - void Serialize(std::stringstream& ss, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ss.write((const char*)&isi, sizeof(isi)); } + void Serialize(EQEmu::OutBuffer& ob, int16 slot_id) const { InternalSerializedItem_Struct isi; isi.slot_id = slot_id; isi.inst = (const void*)this; ob.write((const char*)&isi, sizeof(isi)); } inline int32 GetSerialNumber() const { return m_SerialNumber; } inline void SetSerialNumber(int32 id) { m_SerialNumber = id; } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 49e644412..dc57d0ba6 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -24,7 +24,7 @@ namespace RoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot); @@ -557,24 +557,21 @@ namespace RoF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -1492,30 +1489,24 @@ namespace RoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -5180,7 +5171,7 @@ namespace RoF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -5212,7 +5203,7 @@ namespace RoF hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF::structs::EvolvingItem evotop; @@ -5226,7 +5217,7 @@ namespace RoF evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5241,16 +5232,16 @@ namespace RoF char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); //Offhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); } else { - ss.write("\0", 1); // no main hand Ornamentation - ss.write("\0", 1); // no off hand Ornamentation + ob.write("\0", 1); // no main hand Ornamentation + ob.write("\0", 1); // no off hand Ornamentation } RoF::structs::ItemSerializationHeaderFinish hdrf; @@ -5264,21 +5255,21 @@ namespace RoF hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(RoF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); - ss.write("\0", 1); + ob.write("\0", 1); RoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct)); @@ -5369,12 +5360,12 @@ namespace RoF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(RoF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(RoF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); RoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct)); @@ -5403,11 +5394,11 @@ namespace RoF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(RoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); RoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct)); @@ -5442,7 +5433,7 @@ namespace RoF itbs.unknown13 = 0; itbs.unknown14 = 0; - ss.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(RoF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -5459,13 +5450,13 @@ namespace RoF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(RoF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(RoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 RoF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct)); @@ -5476,13 +5467,13 @@ namespace RoF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(RoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 RoF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5492,13 +5483,13 @@ namespace RoF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5508,13 +5499,13 @@ namespace RoF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(RoF::structs::WornEffectStruct)); @@ -5524,13 +5515,13 @@ namespace RoF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(RoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? RoF::structs::WornEffectStruct ibes; @@ -5542,7 +5533,7 @@ namespace RoF ibes.level = 0; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(RoF::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(RoF::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) @@ -5551,9 +5542,9 @@ namespace RoF ss.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects RoF::structs::ItemQuaternaryBodyStruct iqbs; @@ -5586,12 +5577,12 @@ namespace RoF iqbs.unknown30 = 0; iqbs.unknown39 = 1; - ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -5608,20 +5599,14 @@ namespace RoF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 43cc31d55..a7f63abe6 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -24,7 +24,7 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type); // server to client inventory location converters static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid); @@ -628,24 +628,21 @@ namespace RoF2 InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -1563,29 +1560,24 @@ namespace RoF2 //store away the emu struct uchar* __emu_buffer = in->pBuffer; + ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); + in->size = ob.size(); + in->pBuffer = ob.detach(); delete[] __emu_buffer; @@ -5451,7 +5443,7 @@ namespace RoF2 return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth, ItemPacketType packet_type) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -5483,7 +5475,7 @@ namespace RoF2 hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { RoF2::structs::EvolvingItem evotop; @@ -5497,7 +5489,7 @@ namespace RoF2 evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON @@ -5512,16 +5504,16 @@ namespace RoF2 char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); //Offhand - ss.write(tmp, strlen(tmp)); - ss.write("\0", 1); + ob.write(tmp, strlen(tmp)); + ob.write("\0", 1); } else { - ss.write("\0", 1); // no main hand Ornamentation - ss.write("\0", 1); // no off hand Ornamentation + ob.write("\0", 1); // no main hand Ornamentation + ob.write("\0", 1); // no off hand Ornamentation } RoF2::structs::ItemSerializationHeaderFinish hdrf; @@ -5535,21 +5527,21 @@ namespace RoF2 hdrf.unknowna5 = 0; hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); - ss.write("\0", 1); + ob.write("\0", 1); RoF2::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); @@ -5640,12 +5632,12 @@ namespace RoF2 ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(RoF2::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); RoF2::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); @@ -5674,11 +5666,11 @@ namespace RoF2 isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); RoF2::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); @@ -5713,7 +5705,7 @@ namespace RoF2 itbs.unknown13 = 0; itbs.unknown14 = 0; - ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -5730,13 +5722,13 @@ namespace RoF2 ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 RoF2::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); @@ -5747,13 +5739,13 @@ namespace RoF2 ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 RoF2::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5763,13 +5755,13 @@ namespace RoF2 iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5779,13 +5771,13 @@ namespace RoF2 ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 RoF2::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -5795,13 +5787,13 @@ namespace RoF2 ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? RoF2::structs::WornEffectStruct ibes; @@ -5813,18 +5805,18 @@ namespace RoF2 ibes.level = item->Bard.Level; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(RoF2::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) { - ss.write((const char*)item->BardName, strlen(item->BardName)); - ss.write((const char*)&null_term, sizeof(uint8)); + ob.write((const char*)item->BardName, strlen(item->BardName)); + ob.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects RoF2::structs::ItemQuaternaryBodyStruct iqbs; @@ -5867,12 +5859,12 @@ namespace RoF2 iqbs.unknown38 = 0; iqbs.unknown39 = 1; - ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + EQEmu::OutBuffer::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -5889,20 +5881,14 @@ namespace RoF2 else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1), packet_type); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1), packet_type); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType) diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 9902447b8..b3c5d50d8 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -22,7 +22,7 @@ namespace SoD static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoDSlot(uint32 ServerSlot); @@ -361,25 +361,22 @@ namespace SoD InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1023,30 +1020,24 @@ namespace SoD //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -3540,7 +3531,7 @@ namespace SoD return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -3569,19 +3560,19 @@ namespace SoD hdr.unknown062 = 0; hdr.ItemClass = item->ItemClass; - ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); SoD::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct)); @@ -3670,12 +3661,12 @@ namespace SoD ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(SoD::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(SoD::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); SoD::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct)); @@ -3703,11 +3694,11 @@ namespace SoD isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(SoD::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(SoD::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); SoD::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoD::structs::ItemTertiaryBodyStruct)); @@ -3731,7 +3722,7 @@ namespace SoD itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(SoD::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -3748,13 +3739,13 @@ namespace SoD ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(SoD::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(SoD::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 SoD::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(SoD::structs::ProcEffectStruct)); @@ -3765,13 +3756,13 @@ namespace SoD ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(SoD::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(SoD::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 SoD::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3781,13 +3772,13 @@ namespace SoD iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoD::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3797,13 +3788,13 @@ namespace SoD ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoD::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(SoD::structs::WornEffectStruct)); @@ -3813,13 +3804,13 @@ namespace SoD ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(SoD::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(SoD::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects SoD::structs::ItemQuaternaryBodyStruct iqbs; @@ -3849,12 +3840,12 @@ namespace SoD iqbs.SpellDmg = item->SpellDmg; iqbs.Clairvoyance = item->Clairvoyance; - ss.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -3871,20 +3862,14 @@ namespace SoD else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToSoDSlot(uint32 serverSlot) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index e2526cb45..32383d4e9 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -22,7 +22,7 @@ namespace SoF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToSoFSlot(uint32 serverSlot); @@ -343,25 +343,22 @@ namespace SoF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -823,30 +820,24 @@ namespace SoF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -2865,7 +2856,7 @@ namespace SoF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -2893,19 +2884,19 @@ namespace SoF hdr.unknown061 = 0; hdr.ItemClass = item->ItemClass; - ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); SoF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct)); @@ -2994,12 +2985,12 @@ namespace SoF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(SoF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(SoF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); SoF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct)); @@ -3027,11 +3018,11 @@ namespace SoF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(SoF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(SoF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); SoF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(SoF::structs::ItemTertiaryBodyStruct)); @@ -3055,7 +3046,7 @@ namespace SoF itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(SoF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -3072,13 +3063,13 @@ namespace SoF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(SoF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(SoF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 SoF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(SoF::structs::ProcEffectStruct)); @@ -3089,13 +3080,13 @@ namespace SoF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(SoF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(SoF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 SoF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3105,13 +3096,13 @@ namespace SoF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3121,13 +3112,13 @@ namespace SoF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 SoF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(SoF::structs::WornEffectStruct)); @@ -3137,13 +3128,13 @@ namespace SoF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(SoF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(SoF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects SoF::structs::ItemQuaternaryBodyStruct iqbs; @@ -3172,12 +3163,12 @@ namespace SoF iqbs.HealAmt = item->HealAmt; iqbs.SpellDmg = item->SpellDmg; - ss.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -3194,20 +3185,14 @@ namespace SoF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToSoFSlot(uint32 serverSlot) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index cdfbf0250..b3a27cb7b 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -20,7 +20,7 @@ namespace Titanium static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth); // server to client inventory location converters static inline int16 ServerToTitaniumSlot(uint32 serverSlot); @@ -272,26 +272,24 @@ namespace Titanium delete in; return; } + InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; //do the transform... - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); for (int r = 0; r < itemcount; r++, eq++) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -720,30 +718,24 @@ namespace Titanium //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); + in->size = ob.size(); + in->pBuffer = ob.detach(); - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -2083,241 +2075,241 @@ namespace Titanium } // file scope helper methods - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const char* protection = "\\\\\\\\\\"; const Item_Struct* item = inst->GetUnscaledItem(); - ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; + ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem; // Instance data - ss << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count - ss << '|' << itoa(0); // unknown - ss << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot - ss << '|' << itoa(inst->GetPrice()); // merchant price - ss << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count - ss << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience - ss << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number - ss << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp - ss << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count - ss << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned - ss << '|' << itoa(0); // unknown - ss << '|'; + ob << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count + ob << '|' << itoa(0); // unknown + ob << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot + ob << '|' << itoa(inst->GetPrice()); // merchant price + ob << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count + ob << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience + ob << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number + ob << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp + ob << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count + ob << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned + ob << '|' << itoa(0); // unknown + ob << '|'; - ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data + ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Item data - ss << itoa(item->ItemClass); - ss << '|' << item->Name; - ss << '|' << item->Lore; - ss << '|' << item->IDFile; - ss << '|' << itoa(item->ID); - ss << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight)); + ob << itoa(item->ItemClass); + ob << '|' << item->Name; + ob << '|' << item->Lore; + ob << '|' << item->IDFile; + ob << '|' << itoa(item->ID); + ob << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight)); - ss << '|' << itoa(item->NoRent); - ss << '|' << itoa(item->NoDrop); - ss << '|' << itoa(item->Size); - ss << '|' << itoa(item->Slots); - ss << '|' << itoa(item->Price); - ss << '|' << itoa(item->Icon); - ss << '|' << "0"; - ss << '|' << "0"; - ss << '|' << itoa(item->BenefitFlag); - ss << '|' << itoa(item->Tradeskills); + ob << '|' << itoa(item->NoRent); + ob << '|' << itoa(item->NoDrop); + ob << '|' << itoa(item->Size); + ob << '|' << itoa(item->Slots); + ob << '|' << itoa(item->Price); + ob << '|' << itoa(item->Icon); + ob << '|' << "0"; + ob << '|' << "0"; + ob << '|' << itoa(item->BenefitFlag); + ob << '|' << itoa(item->Tradeskills); - ss << '|' << itoa(item->CR); - ss << '|' << itoa(item->DR); - ss << '|' << itoa(item->PR); - ss << '|' << itoa(item->MR); - ss << '|' << itoa(item->FR); + ob << '|' << itoa(item->CR); + ob << '|' << itoa(item->DR); + ob << '|' << itoa(item->PR); + ob << '|' << itoa(item->MR); + ob << '|' << itoa(item->FR); - ss << '|' << itoa(item->AStr); - ss << '|' << itoa(item->ASta); - ss << '|' << itoa(item->AAgi); - ss << '|' << itoa(item->ADex); - ss << '|' << itoa(item->ACha); - ss << '|' << itoa(item->AInt); - ss << '|' << itoa(item->AWis); + ob << '|' << itoa(item->AStr); + ob << '|' << itoa(item->ASta); + ob << '|' << itoa(item->AAgi); + ob << '|' << itoa(item->ADex); + ob << '|' << itoa(item->ACha); + ob << '|' << itoa(item->AInt); + ob << '|' << itoa(item->AWis); - ss << '|' << itoa(item->HP); - ss << '|' << itoa(item->Mana); - ss << '|' << itoa(item->AC); - ss << '|' << itoa(item->Deity); + ob << '|' << itoa(item->HP); + ob << '|' << itoa(item->Mana); + ob << '|' << itoa(item->AC); + ob << '|' << itoa(item->Deity); - ss << '|' << itoa(item->SkillModValue); - ss << '|' << itoa(item->SkillModMax); - ss << '|' << itoa(item->SkillModType); + ob << '|' << itoa(item->SkillModValue); + ob << '|' << itoa(item->SkillModMax); + ob << '|' << itoa(item->SkillModType); - ss << '|' << itoa(item->BaneDmgRace); - ss << '|' << itoa(item->BaneDmgAmt); - ss << '|' << itoa(item->BaneDmgBody); + ob << '|' << itoa(item->BaneDmgRace); + ob << '|' << itoa(item->BaneDmgAmt); + ob << '|' << itoa(item->BaneDmgBody); - ss << '|' << itoa(item->Magic); - ss << '|' << itoa(item->CastTime_); - ss << '|' << itoa(item->ReqLevel); - ss << '|' << itoa(item->BardType); - ss << '|' << itoa(item->BardValue); - ss << '|' << itoa(item->Light); - ss << '|' << itoa(item->Delay); + ob << '|' << itoa(item->Magic); + ob << '|' << itoa(item->CastTime_); + ob << '|' << itoa(item->ReqLevel); + ob << '|' << itoa(item->BardType); + ob << '|' << itoa(item->BardValue); + ob << '|' << itoa(item->Light); + ob << '|' << itoa(item->Delay); - ss << '|' << itoa(item->RecLevel); - ss << '|' << itoa(item->RecSkill); + ob << '|' << itoa(item->RecLevel); + ob << '|' << itoa(item->RecSkill); - ss << '|' << itoa(item->ElemDmgType); - ss << '|' << itoa(item->ElemDmgAmt); + ob << '|' << itoa(item->ElemDmgType); + ob << '|' << itoa(item->ElemDmgAmt); - ss << '|' << itoa(item->Range); - ss << '|' << itoa(item->Damage); + ob << '|' << itoa(item->Range); + ob << '|' << itoa(item->Damage); - ss << '|' << itoa(item->Color); - ss << '|' << itoa(item->Classes); - ss << '|' << itoa(item->Races); - ss << '|' << "0"; + ob << '|' << itoa(item->Color); + ob << '|' << itoa(item->Classes); + ob << '|' << itoa(item->Races); + ob << '|' << "0"; - ss << '|' << itoa(item->MaxCharges); - ss << '|' << itoa(item->ItemType); - ss << '|' << itoa(item->Material); - ss << '|' << StringFormat("%f", item->SellRate); + ob << '|' << itoa(item->MaxCharges); + ob << '|' << itoa(item->ItemType); + ob << '|' << itoa(item->Material); + ob << '|' << StringFormat("%f", item->SellRate); - ss << '|' << "0"; - ss << '|' << itoa(item->CastTime_); - ss << '|' << "0"; + ob << '|' << "0"; + ob << '|' << itoa(item->CastTime_); + ob << '|' << "0"; - ss << '|' << itoa(item->ProcRate); - ss << '|' << itoa(item->CombatEffects); - ss << '|' << itoa(item->Shielding); - ss << '|' << itoa(item->StunResist); - ss << '|' << itoa(item->StrikeThrough); - ss << '|' << itoa(item->ExtraDmgSkill); - ss << '|' << itoa(item->ExtraDmgAmt); - ss << '|' << itoa(item->SpellShield); - ss << '|' << itoa(item->Avoidance); - ss << '|' << itoa(item->Accuracy); + ob << '|' << itoa(item->ProcRate); + ob << '|' << itoa(item->CombatEffects); + ob << '|' << itoa(item->Shielding); + ob << '|' << itoa(item->StunResist); + ob << '|' << itoa(item->StrikeThrough); + ob << '|' << itoa(item->ExtraDmgSkill); + ob << '|' << itoa(item->ExtraDmgAmt); + ob << '|' << itoa(item->SpellShield); + ob << '|' << itoa(item->Avoidance); + ob << '|' << itoa(item->Accuracy); - ss << '|' << itoa(item->CharmFileID); + ob << '|' << itoa(item->CharmFileID); - ss << '|' << itoa(item->FactionMod1); - ss << '|' << itoa(item->FactionMod2); - ss << '|' << itoa(item->FactionMod3); - ss << '|' << itoa(item->FactionMod4); + ob << '|' << itoa(item->FactionMod1); + ob << '|' << itoa(item->FactionMod2); + ob << '|' << itoa(item->FactionMod3); + ob << '|' << itoa(item->FactionMod4); - ss << '|' << itoa(item->FactionAmt1); - ss << '|' << itoa(item->FactionAmt2); - ss << '|' << itoa(item->FactionAmt3); - ss << '|' << itoa(item->FactionAmt4); + ob << '|' << itoa(item->FactionAmt1); + ob << '|' << itoa(item->FactionAmt2); + ob << '|' << itoa(item->FactionAmt3); + ob << '|' << itoa(item->FactionAmt4); - ss << '|' << item->CharmFile; + ob << '|' << item->CharmFile; - ss << '|' << itoa(item->AugType); + ob << '|' << itoa(item->AugType); - ss << '|' << itoa(item->AugSlotType[0]); - ss << '|' << itoa(item->AugSlotVisible[0]); - ss << '|' << itoa(item->AugSlotType[1]); - ss << '|' << itoa(item->AugSlotVisible[1]); - ss << '|' << itoa(item->AugSlotType[2]); - ss << '|' << itoa(item->AugSlotVisible[2]); - ss << '|' << itoa(item->AugSlotType[3]); - ss << '|' << itoa(item->AugSlotVisible[3]); - ss << '|' << itoa(item->AugSlotType[4]); - ss << '|' << itoa(item->AugSlotVisible[4]); + ob << '|' << itoa(item->AugSlotType[0]); + ob << '|' << itoa(item->AugSlotVisible[0]); + ob << '|' << itoa(item->AugSlotType[1]); + ob << '|' << itoa(item->AugSlotVisible[1]); + ob << '|' << itoa(item->AugSlotType[2]); + ob << '|' << itoa(item->AugSlotVisible[2]); + ob << '|' << itoa(item->AugSlotType[3]); + ob << '|' << itoa(item->AugSlotVisible[3]); + ob << '|' << itoa(item->AugSlotType[4]); + ob << '|' << itoa(item->AugSlotVisible[4]); - ss << '|' << itoa(item->LDoNTheme); - ss << '|' << itoa(item->LDoNPrice); - ss << '|' << itoa(item->LDoNSold); + ob << '|' << itoa(item->LDoNTheme); + ob << '|' << itoa(item->LDoNPrice); + ob << '|' << itoa(item->LDoNSold); - ss << '|' << itoa(item->BagType); - ss << '|' << itoa(item->BagSlots); - ss << '|' << itoa(item->BagSize); - ss << '|' << itoa(item->BagWR); + ob << '|' << itoa(item->BagType); + ob << '|' << itoa(item->BagSlots); + ob << '|' << itoa(item->BagSize); + ob << '|' << itoa(item->BagWR); - ss << '|' << itoa(item->Book); - ss << '|' << itoa(item->BookType); + ob << '|' << itoa(item->Book); + ob << '|' << itoa(item->BookType); - ss << '|' << item->Filename; + ob << '|' << item->Filename; - ss << '|' << itoa(item->BaneDmgRaceAmt); - ss << '|' << itoa(item->AugRestrict); - ss << '|' << itoa(item->LoreGroup); - ss << '|' << itoa(item->PendingLoreFlag); - ss << '|' << itoa(item->ArtifactFlag); - ss << '|' << itoa(item->SummonedFlag); + ob << '|' << itoa(item->BaneDmgRaceAmt); + ob << '|' << itoa(item->AugRestrict); + ob << '|' << itoa(item->LoreGroup); + ob << '|' << itoa(item->PendingLoreFlag); + ob << '|' << itoa(item->ArtifactFlag); + ob << '|' << itoa(item->SummonedFlag); - ss << '|' << itoa(item->Favor); - ss << '|' << itoa(item->FVNoDrop); - ss << '|' << itoa(item->Endur); - ss << '|' << itoa(item->DotShielding); - ss << '|' << itoa(item->Attack); - ss << '|' << itoa(item->Regen); - ss << '|' << itoa(item->ManaRegen); - ss << '|' << itoa(item->EnduranceRegen); - ss << '|' << itoa(item->Haste); - ss << '|' << itoa(item->DamageShield); - ss << '|' << itoa(item->RecastDelay); - ss << '|' << itoa(item->RecastType); - ss << '|' << itoa(item->GuildFavor); + ob << '|' << itoa(item->Favor); + ob << '|' << itoa(item->FVNoDrop); + ob << '|' << itoa(item->Endur); + ob << '|' << itoa(item->DotShielding); + ob << '|' << itoa(item->Attack); + ob << '|' << itoa(item->Regen); + ob << '|' << itoa(item->ManaRegen); + ob << '|' << itoa(item->EnduranceRegen); + ob << '|' << itoa(item->Haste); + ob << '|' << itoa(item->DamageShield); + ob << '|' << itoa(item->RecastDelay); + ob << '|' << itoa(item->RecastType); + ob << '|' << itoa(item->GuildFavor); - ss << '|' << itoa(item->AugDistiller); + ob << '|' << itoa(item->AugDistiller); - ss << '|' << "0"; // unknown - ss << '|' << "0"; // unknown - ss << '|' << itoa(item->Attuneable); - ss << '|' << itoa(item->NoPet); - ss << '|' << "0"; // unknown - ss << '|' << itoa(item->PointType); + ob << '|' << "0"; // unknown + ob << '|' << "0"; // unknown + ob << '|' << itoa(item->Attuneable); + ob << '|' << itoa(item->NoPet); + ob << '|' << "0"; // unknown + ob << '|' << itoa(item->PointType); - ss << '|' << itoa(item->PotionBelt); - ss << '|' << itoa(item->PotionBeltSlots); - ss << '|' << itoa(item->StackSize); - ss << '|' << itoa(item->NoTransfer); - ss << '|' << itoa(item->Stackable); + ob << '|' << itoa(item->PotionBelt); + ob << '|' << itoa(item->PotionBeltSlots); + ob << '|' << itoa(item->StackSize); + ob << '|' << itoa(item->NoTransfer); + ob << '|' << itoa(item->Stackable); - ss << '|' << itoa(item->Click.Effect); - ss << '|' << itoa(item->Click.Type); - ss << '|' << itoa(item->Click.Level2); - ss << '|' << itoa(item->Click.Level); - ss << '|' << "0"; // Click name + ob << '|' << itoa(item->Click.Effect); + ob << '|' << itoa(item->Click.Type); + ob << '|' << itoa(item->Click.Level2); + ob << '|' << itoa(item->Click.Level); + ob << '|' << "0"; // Click name - ss << '|' << itoa(item->Proc.Effect); - ss << '|' << itoa(item->Proc.Type); - ss << '|' << itoa(item->Proc.Level2); - ss << '|' << itoa(item->Proc.Level); - ss << '|' << "0"; // Proc name + ob << '|' << itoa(item->Proc.Effect); + ob << '|' << itoa(item->Proc.Type); + ob << '|' << itoa(item->Proc.Level2); + ob << '|' << itoa(item->Proc.Level); + ob << '|' << "0"; // Proc name - ss << '|' << itoa(item->Worn.Effect); - ss << '|' << itoa(item->Worn.Type); - ss << '|' << itoa(item->Worn.Level2); - ss << '|' << itoa(item->Worn.Level); - ss << '|' << "0"; // Worn name + ob << '|' << itoa(item->Worn.Effect); + ob << '|' << itoa(item->Worn.Type); + ob << '|' << itoa(item->Worn.Level2); + ob << '|' << itoa(item->Worn.Level); + ob << '|' << "0"; // Worn name - ss << '|' << itoa(item->Focus.Effect); - ss << '|' << itoa(item->Focus.Type); - ss << '|' << itoa(item->Focus.Level2); - ss << '|' << itoa(item->Focus.Level); - ss << '|' << "0"; // Focus name + ob << '|' << itoa(item->Focus.Effect); + ob << '|' << itoa(item->Focus.Type); + ob << '|' << itoa(item->Focus.Level2); + ob << '|' << itoa(item->Focus.Level); + ob << '|' << "0"; // Focus name - ss << '|' << itoa(item->Scroll.Effect); - ss << '|' << itoa(item->Scroll.Type); - ss << '|' << itoa(item->Scroll.Level2); - ss << '|' << itoa(item->Scroll.Level); - ss << '|' << "0"; // Scroll name + ob << '|' << itoa(item->Scroll.Effect); + ob << '|' << itoa(item->Scroll.Type); + ob << '|' << itoa(item->Scroll.Level2); + ob << '|' << itoa(item->Scroll.Level); + ob << '|' << "0"; // Scroll name - ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data + ob << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data // Sub data for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) { - ss << '|'; + ob << '|'; ItemInst* sub = inst->GetItem(index); if (!sub) continue; - SerializeItem(ss, sub, 0, (depth + 1)); + SerializeItem(ob, sub, 0, (depth + 1)); } - ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem; + ob << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem; if (!depth) - ss.write("\0", 1); + ob.write("\0", 1); } static inline int16 ServerToTitaniumSlot(uint32 serverSlot) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index f864172bd..24b4b6cba 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -22,7 +22,7 @@ namespace UF static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth); + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id, uint8 depth); // server to client inventory location converters static inline uint32 ServerToUFSlot(uint32 serverSlot); @@ -499,25 +499,22 @@ namespace UF InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer; - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)&item_count, sizeof(uint32)); + ob.write((const char*)&item_count, sizeof(uint32)); for (int index = 0; index < item_count; ++index, ++eq) { - SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0); - if (ss.tellp() == last_pos) + SerializeItem(ob, (const ItemInst*)eq->inst, eq->slot_id, 0); + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -1249,30 +1246,24 @@ namespace UF //store away the emu struct uchar* __emu_buffer = in->pBuffer; - //ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer; - //InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem); + InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); - ss.write((const char*)__emu_buffer, 4); + ob.write((const char*)__emu_buffer, 4); - SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); - if (ss.tellp() == last_pos) { + SerializeItem(ob, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0); + if (ob.tellp() == last_pos) { Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id); delete in; return; } - std::string serialized = ss.str(); - - in->size = serialized.size(); - in->pBuffer = new uchar[in->size]; - //ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer; - //new_item_pkt->PacketType = old_item_pkt->PacketType; - memcpy(in->pBuffer, serialized.c_str(), serialized.size()); - + in->size = ob.size(); + in->pBuffer = ob.detach(); + delete[] __emu_buffer; dest->FastQueuePacket(&in, ack_req); @@ -3815,7 +3806,7 @@ namespace UF return NextItemInstSerialNumber; } - void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth) + void SerializeItem(EQEmu::OutBuffer& ob, const ItemInst *inst, int16 slot_id_in, uint8 depth) { const Item_Struct *item = inst->GetUnscaledItem(); @@ -3840,7 +3831,7 @@ namespace UF hdr.unknown052 = 0; hdr.isEvolving = item->EvolvingItem; - ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); + ob.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader)); if (item->EvolvingItem > 0) { UF::structs::EvolvingItem evotop; @@ -3854,7 +3845,7 @@ namespace UF evotop.Activated = 1; evotop.evomaxlevel = item->EvolvingMax; - ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); + ob.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem)); } //ORNAMENT IDFILE / ICON - @@ -3864,15 +3855,15 @@ namespace UF const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem(); ornaIcon = aug_weap->Icon; - ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); + ob.write(aug_weap->IDFile, strlen(aug_weap->IDFile)); } else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) { ornaIcon = inst->GetOrnamentationIcon(); char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - ss.write(tmp, strlen(tmp)); + ob.write(tmp, strlen(tmp)); } - ss.write("\0", 1); + ob.write("\0", 1); UF::structs::ItemSerializationHeaderFinish hdrf; @@ -3882,19 +3873,19 @@ namespace UF hdrf.isCopied = 0; //Flag for item to be 'Copied' hdrf.ItemClass = item->ItemClass; - ss.write((const char*)&hdrf, sizeof(UF::structs::ItemSerializationHeaderFinish)); + ob.write((const char*)&hdrf, sizeof(UF::structs::ItemSerializationHeaderFinish)); if (strlen(item->Name) > 0) - ss.write(item->Name, strlen(item->Name)); - ss.write("\0", 1); + ob.write(item->Name, strlen(item->Name)); + ob.write("\0", 1); if (strlen(item->Lore) > 0) - ss.write(item->Lore, strlen(item->Lore)); - ss.write("\0", 1); + ob.write(item->Lore, strlen(item->Lore)); + ob.write("\0", 1); if (strlen(item->IDFile) > 0) - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write("\0", 1); + ob.write(item->IDFile, strlen(item->IDFile)); + ob.write("\0", 1); UF::structs::ItemBodyStruct ibs; memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct)); @@ -3983,12 +3974,12 @@ namespace UF ibs.FactionAmt4 = item->FactionAmt4; ibs.FactionMod4 = item->FactionMod4; - ss.write((const char*)&ibs, sizeof(UF::structs::ItemBodyStruct)); + ob.write((const char*)&ibs, sizeof(UF::structs::ItemBodyStruct)); //charm text if (strlen(item->CharmFile) > 0) - ss.write((const char*)item->CharmFile, strlen(item->CharmFile)); - ss.write("\0", 1); + ob.write((const char*)item->CharmFile, strlen(item->CharmFile)); + ob.write("\0", 1); UF::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(UF::structs::ItemSecondaryBodyStruct)); @@ -4016,11 +4007,11 @@ namespace UF isbs.book = item->Book; isbs.booktype = item->BookType; - ss.write((const char*)&isbs, sizeof(UF::structs::ItemSecondaryBodyStruct)); + ob.write((const char*)&isbs, sizeof(UF::structs::ItemSecondaryBodyStruct)); if (strlen(item->Filename) > 0) - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write("\0", 1); + ob.write((const char*)item->Filename, strlen(item->Filename)); + ob.write("\0", 1); UF::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(UF::structs::ItemTertiaryBodyStruct)); @@ -4044,7 +4035,7 @@ namespace UF itbs.no_transfer = item->NoTransfer; itbs.expendablearrow = item->ExpendableArrow; - ss.write((const char*)&itbs, sizeof(UF::structs::ItemTertiaryBodyStruct)); + ob.write((const char*)&itbs, sizeof(UF::structs::ItemTertiaryBodyStruct)); // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; @@ -4061,13 +4052,13 @@ namespace UF ices.recast = item->RecastDelay; ices.recast_type = item->RecastType; - ss.write((const char*)&ices, sizeof(UF::structs::ClickEffectStruct)); + ob.write((const char*)&ices, sizeof(UF::structs::ClickEffectStruct)); if (strlen(item->ClickName) > 0) - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write("\0", 1); + ob.write((const char*)item->ClickName, strlen(item->ClickName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + ob.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 UF::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(UF::structs::ProcEffectStruct)); @@ -4078,13 +4069,13 @@ namespace UF ipes.level = item->Proc.Level; ipes.procrate = item->ProcRate; - ss.write((const char*)&ipes, sizeof(UF::structs::ProcEffectStruct)); + ob.write((const char*)&ipes, sizeof(UF::structs::ProcEffectStruct)); if (strlen(item->ProcName) > 0) - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write("\0", 1); + ob.write((const char*)item->ProcName, strlen(item->ProcName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 UF::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4094,13 +4085,13 @@ namespace UF iwes.type = item->Worn.Type; iwes.level = item->Worn.Level; - ss.write((const char*)&iwes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&iwes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->WornName) > 0) - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write("\0", 1); + ob.write((const char*)item->WornName, strlen(item->WornName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 UF::structs::WornEffectStruct ifes; memset(&ifes, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4110,13 +4101,13 @@ namespace UF ifes.type = item->Focus.Type; ifes.level = item->Focus.Level; - ss.write((const char*)&ifes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ifes, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->FocusName) > 0) - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write("\0", 1); + ob.write((const char*)item->FocusName, strlen(item->FocusName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 UF::structs::WornEffectStruct ises; memset(&ises, 0, sizeof(UF::structs::WornEffectStruct)); @@ -4126,13 +4117,13 @@ namespace UF ises.type = item->Scroll.Type; ises.level = item->Scroll.Level; - ss.write((const char*)&ises, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ises, sizeof(UF::structs::WornEffectStruct)); if (strlen(item->ScrollName) > 0) - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write("\0", 1); + ob.write((const char*)item->ScrollName, strlen(item->ScrollName)); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // Bard Effect? UF::structs::WornEffectStruct ibes; @@ -4144,18 +4135,18 @@ namespace UF ibes.level = item->Bard.Level; //ibes.unknown6 = 0xffffffff; - ss.write((const char*)&ibes, sizeof(UF::structs::WornEffectStruct)); + ob.write((const char*)&ibes, sizeof(UF::structs::WornEffectStruct)); /* if(strlen(item->BardName) > 0) { - ss.write((const char*)item->BardName, strlen(item->BardName)); - ss.write((const char*)&null_term, sizeof(uint8)); + ob.write((const char*)item->BardName, strlen(item->BardName)); + ob.write((const char*)&null_term, sizeof(uint8)); } else */ - ss.write("\0", 1); + ob.write("\0", 1); - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + ob.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects UF::structs::ItemQuaternaryBodyStruct iqbs; @@ -4185,12 +4176,12 @@ namespace UF iqbs.SpellDmg = item->SpellDmg; iqbs.Clairvoyance = item->Clairvoyance; - ss.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); + ob.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct)); - std::stringstream::pos_type count_pos = ss.tellp(); + std::stringstream::pos_type count_pos = ob.tellp(); uint32 subitem_count = 0; - ss.write((const char*)&subitem_count, sizeof(uint32)); + ob.write((const char*)&subitem_count, sizeof(uint32)); for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) { ItemInst* sub = inst->GetItem(index); @@ -4207,20 +4198,14 @@ namespace UF else SubSlotNumber = slot_id_in; - ss.write((const char*)&index, sizeof(uint32)); + ob.write((const char*)&index, sizeof(uint32)); - SerializeItem(ss, sub, SubSlotNumber, (depth + 1)); + SerializeItem(ob, sub, SubSlotNumber, (depth + 1)); ++subitem_count; } - if (subitem_count) { - std::stringstream::pos_type cur_pos = ss.tellp(); - ss.seekp(count_pos); - - ss.write((const char*)&subitem_count, sizeof(uint32)); - - ss.seekp(cur_pos); - } + if (subitem_count) + ob.overwrite(count_pos, (const char*)&subitem_count, sizeof(uint32)); } static inline uint32 ServerToUFSlot(uint32 serverSlot) diff --git a/common/string_util.cpp b/common/string_util.cpp index e791eb7f6..96cfce310 100644 --- a/common/string_util.cpp +++ b/common/string_util.cpp @@ -415,3 +415,46 @@ void find_replace(std::string& string_subject, const std::string& search_string, index = string_subject.find_first_of(search_string); } } + + + +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 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 +*/ + + +void EQEmu::OutBuffer::overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count) +{ + auto last_pos = tellp(); + seekp(position); + write(_Str, _Count); + seekp(last_pos); +} + +uchar* EQEmu::OutBuffer::detach() +{ + size_t buffer_size = tellp(); + if (buffer_size == 0) + return nullptr; + + uchar* out_buffer = new uchar[buffer_size]; + memcpy(out_buffer, str().c_str(), buffer_size); + flush(); + + return out_buffer; +} diff --git a/common/string_util.h b/common/string_util.h index c69f01456..5b373a41b 100644 --- a/common/string_util.h +++ b/common/string_util.h @@ -53,4 +53,36 @@ void MakeLowerString(const char *source, char *target); void RemoveApostrophes(std::string &s); void find_replace(std::string& string_subject, const std::string& search_string, const std::string& replace_string); + + +/* EQEMu: Everquest Server Emulator + + Copyright (C) 2001-2016 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 +*/ + + +namespace EQEmu +{ + class OutBuffer : public std::stringstream { + public: + inline size_t size() { return tellp(); } + void overwrite(OutBuffer::pos_type position, const char *_Str, std::streamsize _Count); + uchar* detach(); + }; +} + #endif diff --git a/zone/client_process.cpp b/zone/client_process.cpp index 8c58049ab..6dcca861e 100644 --- a/zone/client_process.cpp +++ b/zone/client_process.cpp @@ -759,8 +759,8 @@ void Client::BulkSendInventoryItems() RemoveDuplicateLore(false); MoveSlotNotAllowed(false); - std::stringstream ss(std::stringstream::in | std::stringstream::out); - std::stringstream::pos_type last_pos = ss.tellp(); + EQEmu::OutBuffer ob; + EQEmu::OutBuffer::pos_type last_pos = ob.tellp(); // Possessions items for (int16 slot_id = SLOT_BEGIN; slot_id < EQEmu::legacy::TYPE_POSSESSIONS_SIZE; slot_id++) { @@ -768,24 +768,24 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } // PowerSource item if (ClientVersion() >= EQEmu::versions::ClientVersion::SoF) { const ItemInst* inst = m_inv[EQEmu::legacy::SlotPowerSource]; if (inst) { - inst->Serialize(ss, EQEmu::legacy::SlotPowerSource); + inst->Serialize(ob, EQEmu::legacy::SlotPowerSource); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", EQEmu::legacy::SlotPowerSource); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } } @@ -795,12 +795,12 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } // SharedBank items @@ -809,19 +809,17 @@ void Client::BulkSendInventoryItems() if (!inst) continue; - inst->Serialize(ss, slot_id); + inst->Serialize(ob, slot_id); - if (ss.tellp() == last_pos) + if (ob.tellp() == last_pos) Log.Out(Logs::General, Logs::Inventory, "Serialization failed on item slot %d during BulkSendInventoryItems. Item skipped.", slot_id); - last_pos = ss.tellp(); + last_pos = ob.tellp(); } - std::string serialized = ss.str(); - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory, serialized.size()); - memcpy(outapp->pBuffer, serialized.c_str(), serialized.size()); - + EQApplicationPacket* outapp = new EQApplicationPacket(OP_CharInventory); + outapp->size = ob.size(); + outapp->pBuffer = ob.detach(); QueuePacket(outapp); safe_delete(outapp); }