From 69612b44d48652cc3758938c523d1eb8ff5b1f82 Mon Sep 17 00:00:00 2001 From: KimLS Date: Mon, 23 Feb 2015 22:45:50 -0800 Subject: [PATCH] OP_MoveItem encode/decode for RoF2, disabled other patches for now (until i get rof2 packets and mechanics working well enough to go back and fix those) --- common/eq_packet_structs.h | 15 +- common/inventory.cpp | 58 +- common/inventory.h | 43 +- common/item_instance.cpp | 42 ++ common/item_instance.h | 9 + common/memory_buffer.cpp | 36 +- common/patches/patches.cpp | 20 +- common/patches/rof.cpp | 36 +- common/patches/rof2.cpp | 1179 ++++++++++++++++++----------------- common/patches/sod.cpp | 36 +- common/patches/sof.cpp | 36 +- common/patches/titanium.cpp | 36 +- common/patches/uf.cpp | 36 +- tests/inventory_test.h | 2 +- tests/memory_buffer_test.h | 17 + zone/client.h | 6 +- zone/client_packet.cpp | 119 ++-- zone/command.cpp | 142 ++--- zone/inventory.cpp | 238 +++---- zone/trading.cpp | 806 ++++++++++++------------ 20 files changed, 1560 insertions(+), 1352 deletions(-) diff --git a/common/eq_packet_structs.h b/common/eq_packet_structs.h index eec3ecba9..1301b8996 100644 --- a/common/eq_packet_structs.h +++ b/common/eq_packet_structs.h @@ -1556,7 +1556,7 @@ struct DeleteItem_Struct { /*0012*/ }; -struct MoveItem_Struct +struct MoveItemOld_Struct { /*0000*/ uint32 from_slot; /*0004*/ uint32 to_slot; @@ -1564,6 +1564,19 @@ struct MoveItem_Struct /*0012*/ }; +struct MoveItem_Struct +{ + int16 from_type; + int16 from_slot; + int16 from_bag_slot; + int16 from_aug_slot; + int16 to_type; + int16 to_slot; + int16 to_bag_slot; + int16 to_aug_slot; + uint32 number_in_stack; +}; + // both MoveItem_Struct/DeleteItem_Struct server structures will be changing to a structure-based slot format..this will // be used for handling SoF/SoD/etc... time stamps sent using the MoveItem_Struct format. (nothing will be done with this // info at the moment..but, it is forwarded on to the server for handling/future use) diff --git a/common/inventory.cpp b/common/inventory.cpp index 05ae27690..72b6bc59d 100644 --- a/common/inventory.cpp +++ b/common/inventory.cpp @@ -61,6 +61,8 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptrcontainers_.insert(std::pair(slot.type_, ItemContainer())); } + //Verify item can be put into the slot requested + auto &container = impl_->containers_[slot.type_]; if(slot.bag_index_ > -1) { auto item = container.Get(slot.slot_); @@ -92,10 +94,64 @@ bool EQEmu::Inventory::Put(const InventorySlot &slot, std::shared_ptr Get(const InventorySlot &slot); bool Put(const InventorySlot &slot, std::shared_ptr inst); - bool Swap(const InventorySlot &src, const InventorySlot &dest); + bool Swap(const InventorySlot &src, const InventorySlot &dest, int charges); + //utility + static int CalcMaterialFromSlot(const InventorySlot &slot); + static InventorySlot CalcSlotFromMaterial(int material); bool Serialize(MemoryBuffer &buf); private: struct impl; diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 34f9e9cbf..c95c8e72d 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -192,14 +192,56 @@ void EQEmu::ItemInstance::SetCustomData(const std::string &custom_data) { impl_->custom_data_ = custom_data; } +uint32 EQEmu::ItemInstance::GetOrnamentIDFile() { + return impl_->ornament_idfile_; +} + +uint32 EQEmu::ItemInstance::GetOrnamentIDFile() const { + return impl_->ornament_idfile_; +} + void EQEmu::ItemInstance::SetOrnamentIDFile(const uint32 ornament_idfile) { impl_->ornament_idfile_ = ornament_idfile; } +uint32 EQEmu::ItemInstance::GetOrnamentIcon() { + return impl_->ornament_icon_; +} + +uint32 EQEmu::ItemInstance::GetOrnamentIcon() const { + return impl_->ornament_icon_; +} + void EQEmu::ItemInstance::SetOrnamentIcon(const uint32 ornament_icon) { impl_->ornament_icon_ = ornament_icon; } +uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) { + uint32 hero_model = 0; + if(impl_->ornament_hero_model_ > 0) + { + hero_model = impl_->ornament_hero_model_; + if(material_slot >= 0) + { + hero_model = (impl_->ornament_hero_model_ * 100) + material_slot; + } + } + return hero_model; +} + +uint32 EQEmu::ItemInstance::GetOrnamentHeroModel(int material_slot) const { + uint32 hero_model = 0; + if(impl_->ornament_hero_model_ > 0) + { + hero_model = impl_->ornament_hero_model_; + if(material_slot >= 0) + { + hero_model = (impl_->ornament_hero_model_ * 100) + material_slot; + } + } + return hero_model; +} + void EQEmu::ItemInstance::SetOrnamentHeroModel(const uint32 ornament_hero_model) { impl_->ornament_hero_model_ = ornament_hero_model; } diff --git a/common/item_instance.h b/common/item_instance.h index 4fffaf7ee..595bff390 100644 --- a/common/item_instance.h +++ b/common/item_instance.h @@ -53,8 +53,17 @@ namespace EQEmu void SetAttuned(const bool attuned); void SetCustomData(const std::string &custom_data); + + uint32 GetOrnamentIDFile(); + uint32 GetOrnamentIDFile() const; void SetOrnamentIDFile(const uint32 ornament_idfile); + + uint32 GetOrnamentIcon(); + uint32 GetOrnamentIcon() const; void SetOrnamentIcon(const uint32 ornament_icon); + + uint32 GetOrnamentHeroModel(int material_slot); + uint32 GetOrnamentHeroModel(int material_slot) const; void SetOrnamentHeroModel(const uint32 ornament_hero_model); const char* GetTrackingID(); diff --git a/common/memory_buffer.cpp b/common/memory_buffer.cpp index c8ebaf5b8..0910289e2 100644 --- a/common/memory_buffer.cpp +++ b/common/memory_buffer.cpp @@ -32,20 +32,30 @@ EQEmu::MemoryBuffer::MemoryBuffer(const MemoryBuffer &other) { } EQEmu::MemoryBuffer::MemoryBuffer(MemoryBuffer &&other) { - buffer_ = other.buffer_; - size_ = other.size_; - capacity_ = other.capacity_; - write_pos_ = other.write_pos_; - read_pos_ = other.read_pos_; + uchar *tbuf = other.buffer_; + size_t tsz = other.size_; + size_t tcapacity = other.capacity_; + size_t twrite_pos = other.write_pos_; + size_t tread_pos = other.read_pos_; other.buffer_ = nullptr; other.size_ = 0; other.capacity_ = 0; other.read_pos_ = 0; other.write_pos_ = 0; + + buffer_ = tbuf; + size_ = tsz; + capacity_ = tcapacity; + write_pos_ = twrite_pos; + read_pos_ = tread_pos; } EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) { + if(buffer_) { + delete[] buffer_; + } + if(other.capacity_) { buffer_ = new uchar[other.capacity_]; memcpy(buffer_, other.buffer_, other.capacity_); @@ -62,17 +72,23 @@ EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(const MemoryBuffer &other) { } EQEmu::MemoryBuffer& EQEmu::MemoryBuffer::operator=(MemoryBuffer &&other) { - buffer_ = other.buffer_; - size_ = other.size_; - capacity_ = other.capacity_; - write_pos_ = other.write_pos_; - read_pos_ = other.read_pos_; + uchar *tbuf = other.buffer_; + size_t tsz = other.size_; + size_t tcapacity = other.capacity_; + size_t twrite_pos = other.write_pos_; + size_t tread_pos = other.read_pos_; other.buffer_ = nullptr; other.size_ = 0; other.capacity_ = 0; other.read_pos_ = 0; other.write_pos_ = 0; + + buffer_ = tbuf; + size_ = tsz; + capacity_ = tcapacity; + write_pos_ = twrite_pos; + read_pos_ = tread_pos; return *this; } diff --git a/common/patches/patches.cpp b/common/patches/patches.cpp index 3147b89f6..37ff776bc 100644 --- a/common/patches/patches.cpp +++ b/common/patches/patches.cpp @@ -10,19 +10,19 @@ #include "rof2.h" void RegisterAllPatches(EQStreamIdentifier &into) { - Titanium::Register(into); - SoF::Register(into); - SoD::Register(into); - UF::Register(into); - RoF::Register(into); + //Titanium::Register(into); + //SoF::Register(into); + //SoD::Register(into); + //UF::Register(into); + //RoF::Register(into); RoF2::Register(into); } void ReloadAllPatches() { - Titanium::Reload(); - SoF::Reload(); - SoD::Reload(); - UF::Reload(); - RoF::Reload(); + //Titanium::Reload(); + //SoF::Reload(); + //SoD::Reload(); + //UF::Reload(); + //RoF::Reload(); RoF2::Reload(); } diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index a54f0872c..339dd5e2b 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -1707,14 +1707,14 @@ namespace RoF ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToRoFSlot(emu->from_slot); - eq->to_slot = ServerToRoFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); + //ENCODE_LENGTH_EXACT(MoveItem_Struct); + //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //eq->from_slot = ServerToRoFSlot(emu->from_slot); + //eq->to_slot = ServerToRoFSlot(emu->to_slot); + //OUT(number_in_stack); + // + //FINISH_ENCODE(); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } @@ -4684,16 +4684,16 @@ namespace RoF DECODE(OP_MoveItem) { - DECODE_LENGTH_EXACT(structs::MoveItem_Struct); - SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); - Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); - emu->from_slot = RoFToServerSlot(eq->from_slot); - emu->to_slot = RoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - FINISH_DIRECT_DECODE(); + //DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + // + ////Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Moved item from %u to %u", eq->from_slot.MainSlot, eq->to_slot.MainSlot); + //Log.Out(Logs::General, Logs::Netcode, "[RoF] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); + //emu->from_slot = RoFToServerSlot(eq->from_slot); + //emu->to_slot = RoFToServerSlot(eq->to_slot); + //IN(number_in_stack); + // + //FINISH_DIRECT_DECODE(); } DECODE(OP_PetCommands) diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index 561b40234..c3a1fd0f4 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -13,7 +13,7 @@ #include "rof2_structs.h" #include "../rulesys.h" #include "../memory_buffer.h" -#include "../item_instance.h" +#include "../inventory.h" #include #include @@ -26,7 +26,6 @@ namespace RoF2 static OpcodeManager *opcodes = nullptr; static Strategy struct_strategy; - char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth, ItemPacketType packet_type); void SerializeItem(EQEmu::MemoryBuffer &packet_data, EQEmu::ItemInstance *inst, int container_id, int slot_id, int bag_id, int aug_id); // server to client inventory location converters @@ -1749,9 +1748,15 @@ namespace RoF2 ENCODE_LENGTH_EXACT(MoveItem_Struct); SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - eq->from_slot = ServerToRoF2Slot(emu->from_slot); - eq->to_slot = ServerToRoF2Slot(emu->to_slot); - OUT(number_in_stack); + eq->from_slot.SlotType = emu->from_type; + eq->from_slot.MainSlot = emu->from_slot; + eq->from_slot.SubSlot = emu->from_bag_slot; + eq->from_slot.AugSlot = emu->from_aug_slot; + eq->to_slot.SlotType = emu->to_type; + eq->to_slot.MainSlot = emu->to_slot; + eq->to_slot.SubSlot = emu->to_bag_slot; + eq->to_slot.AugSlot = emu->to_aug_slot; + eq->number_in_stack = emu->number_in_stack; FINISH_ENCODE(); } @@ -4804,11 +4809,16 @@ namespace RoF2 DECODE_LENGTH_EXACT(structs::MoveItem_Struct); SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - Log.Out(Logs::General, Logs::Netcode, "[RoF2] MoveItem SlotType from %i to %i, MainSlot from %i to %i, SubSlot from %i to %i, AugSlot from %i to %i, Unknown01 from %i to %i, Number %u", eq->from_slot.SlotType, eq->to_slot.SlotType, eq->from_slot.MainSlot, eq->to_slot.MainSlot, eq->from_slot.SubSlot, eq->to_slot.SubSlot, eq->from_slot.AugSlot, eq->to_slot.AugSlot, eq->from_slot.Unknown01, eq->to_slot.Unknown01, eq->number_in_stack); - emu->from_slot = RoF2ToServerSlot(eq->from_slot); - emu->to_slot = RoF2ToServerSlot(eq->to_slot); - IN(number_in_stack); - + emu->from_type = eq->from_slot.SlotType; + emu->from_slot = eq->from_slot.MainSlot; + emu->from_bag_slot = eq->from_slot.SubSlot; + emu->from_aug_slot = eq->from_slot.AugSlot; + emu->to_type = eq->to_slot.SlotType; + emu->to_slot = eq->to_slot.MainSlot; + emu->to_bag_slot = eq->to_slot.SubSlot; + emu->to_aug_slot = eq->to_slot.AugSlot; + emu->number_in_stack = eq->number_in_stack; + FINISH_DIRECT_DECODE(); } @@ -5183,560 +5193,560 @@ namespace RoF2 return NextItemInstSerialNumber; } - char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) - { - int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); - uint8 null_term = 0; - bool stackable = inst->IsStackable(); - uint32 merchant_slot = inst->GetMerchantSlot(); - uint32 charges = inst->GetCharges(); - if (!stackable && charges > 254) - charges = 0xFFFFFFFF; - - std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); - - const ItemData *item = inst->GetUnscaledItem(); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); - - RoF2::structs::ItemSerializationHeader hdr; - - //sprintf(hdr.unknown000, "06e0002Y1W00"); - - snprintf(hdr.tracking_id, sizeof(hdr.tracking_id), "%016d", item->ID); - - hdr.stacksize = stackable ? charges : 1; - hdr.unknown004 = 0; - - structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); - - hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? - hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; - hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; - hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; - hdr.price = inst->GetPrice(); - hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); - hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; - hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; - hdr.unknown028 = 0; - hdr.last_cast_time = inst->GetRecastTimestamp(); - hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); - hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; - hdr.unknown044 = 0; - hdr.unknown048 = 0; - hdr.unknown052 = 0; - hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; - ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); - - if (item->EvolvingLevel > 0) { - RoF2::structs::EvolvingItem evotop; - evotop.unknown001 = 0; - evotop.unknown002 = 0; - evotop.unknown003 = 0; - evotop.unknown004 = 0; - evotop.evoLevel = item->EvolvingLevel; - evotop.progress = 95.512; - evotop.Activated = 1; - evotop.evomaxlevel = 7; - ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); - } - //ORNAMENT IDFILE / ICON - uint32 ornaIcon = 0; - uint32 heroModel = 0; - - if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) - { - char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - //Mainhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); - //Offhand - ss.write(tmp, strlen(tmp)); - ss.write((const char*)&null_term, sizeof(uint8)); - ornaIcon = inst->GetOrnamentationIcon(); - heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation - ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation - } - - RoF2::structs::ItemSerializationHeaderFinish hdrf; - hdrf.ornamentIcon = ornaIcon; - hdrf.unknowna1 = 0xffffffff; - hdrf.ornamentHeroModel = heroModel; - hdrf.unknown063 = 0; - hdrf.Copied = 0; - hdrf.unknowna4 = 0xffffffff; - hdrf.unknowna5 = 0; - hdrf.ItemClass = item->ItemClass; - - ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); - - if (strlen(item->Name) > 0) - { - ss.write(item->Name, strlen(item->Name)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - if (strlen(item->Lore) > 0) - { - ss.write(item->Lore, strlen(item->Lore)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - if (strlen(item->IDFile) > 0) - { - ss.write(item->IDFile, strlen(item->IDFile)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&null_term, sizeof(uint8)); - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); - RoF2::structs::ItemBodyStruct ibs; - memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); - - ibs.id = item->ID; - ibs.weight = item->Weight; - ibs.norent = item->NoRent; - ibs.nodrop = item->NoDrop; - ibs.attune = item->Attuneable; - ibs.size = item->Size; - ibs.slots = SwapBits21and22(item->Slots); - ibs.price = item->Price; - ibs.icon = item->Icon; - ibs.unknown1 = 1; - ibs.unknown2 = 1; - ibs.BenefitFlag = item->BenefitFlag; - ibs.tradeskills = item->Tradeskills; - ibs.CR = item->CR; - ibs.DR = item->DR; - ibs.PR = item->PR; - ibs.MR = item->MR; - ibs.FR = item->FR; - ibs.SVCorruption = item->SVCorruption; - ibs.AStr = item->AStr; - ibs.ASta = item->ASta; - ibs.AAgi = item->AAgi; - ibs.ADex = item->ADex; - ibs.ACha = item->ACha; - ibs.AInt = item->AInt; - ibs.AWis = item->AWis; - - ibs.HP = item->HP; - ibs.Mana = item->Mana; - ibs.Endur = item->Endur; - ibs.AC = item->AC; - ibs.regen = item->Regen; - ibs.mana_regen = item->ManaRegen; - ibs.end_regen = item->EnduranceRegen; - ibs.Classes = item->Classes; - ibs.Races = item->Races; - ibs.Deity = item->Deity; - ibs.SkillModValue = item->SkillModValue; - ibs.SkillModMax = 0xffffffff; - ibs.SkillModType = (int8)(item->SkillModType); - ibs.SkillModExtra = 0; - ibs.BaneDmgRace = item->BaneDmgRace; - ibs.BaneDmgBody = item->BaneDmgBody; - ibs.BaneDmgRaceAmt = item->BaneDmgRaceAmt; - ibs.BaneDmgAmt = item->BaneDmgAmt; - ibs.Magic = item->Magic; - ibs.CastTime_ = item->CastTime_; - ibs.ReqLevel = item->ReqLevel; - if (item->ReqLevel > 100) - ibs.ReqLevel = 100; - ibs.RecLevel = item->RecLevel; - if (item->RecLevel > 100) - ibs.RecLevel = 100; - ibs.RecSkill = item->RecSkill; - ibs.BardType = item->BardType; - ibs.BardValue = item->BardValue; - ibs.Light = item->Light; - ibs.Delay = item->Delay; - ibs.ElemDmgType = item->ElemDmgType; - ibs.ElemDmgAmt = item->ElemDmgAmt; - ibs.Range = item->Range; - ibs.Damage = item->Damage; - ibs.Color = item->Color; - ibs.Prestige = 0; - ibs.ItemType = item->ItemType; - ibs.Material = item->Material; - ibs.MaterialUnknown1 = 0; - ibs.EliteMaterial = item->EliteMaterial; - ibs.HerosForgeModel = item->HerosForgeModel; - ibs.MaterialUnknown2 = 0; - ibs.SellRate = item->SellRate; - ibs.CombatEffects = item->CombatEffects; - ibs.Shielding = item->Shielding; - ibs.StunResist = item->StunResist; - ibs.StrikeThrough = item->StrikeThrough; - ibs.ExtraDmgSkill = item->ExtraDmgSkill; - ibs.ExtraDmgAmt = item->ExtraDmgAmt; - ibs.SpellShield = item->SpellShield; - ibs.Avoidance = item->Avoidance; - ibs.Accuracy = item->Accuracy; - ibs.CharmFileID = item->CharmFileID; - ibs.FactionAmt1 = item->FactionAmt1; - ibs.FactionMod1 = item->FactionMod1; - ibs.FactionAmt2 = item->FactionAmt2; - ibs.FactionMod2 = item->FactionMod2; - ibs.FactionAmt3 = item->FactionAmt3; - ibs.FactionMod3 = item->FactionMod3; - ibs.FactionAmt4 = item->FactionAmt4; - ibs.FactionMod4 = item->FactionMod4; - - ss.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((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); - RoF2::structs::ItemSecondaryBodyStruct isbs; - memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); - - isbs.augtype = item->AugType; - isbs.augrestrict2 = -1; - isbs.augrestrict = item->AugRestrict; - - for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) - { - isbs.augslots[x].type = item->AugSlotType[x]; - isbs.augslots[x].visible = item->AugSlotVisible[x]; - isbs.augslots[x].unknown = item->AugSlotUnk2[x]; - } - - isbs.ldonpoint_type = item->PointType; - isbs.ldontheme = item->LDoNTheme; - isbs.ldonprice = item->LDoNPrice; - isbs.ldonsellbackrate = item->LDoNSellBackRate; - isbs.ldonsold = item->LDoNSold; - - isbs.bagtype = item->BagType; - isbs.bagslots = item->BagSlots; - isbs.bagsize = item->BagSize; - isbs.wreduction = item->BagWR; - - isbs.book = item->Book; - isbs.booktype = item->BookType; - - ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); - - if (strlen(item->Filename) > 0) - { - ss.write((const char*)item->Filename, strlen(item->Filename)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); - RoF2::structs::ItemTertiaryBodyStruct itbs; - memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); - - itbs.loregroup = item->LoreGroup; - itbs.artifact = item->ArtifactFlag; - itbs.summonedflag = item->SummonedFlag; - itbs.favor = item->Favor; - itbs.fvnodrop = item->FVNoDrop; - itbs.dotshield = item->DotShielding; - itbs.atk = item->Attack; - itbs.haste = item->Haste; - itbs.damage_shield = item->DamageShield; - itbs.guildfavor = item->GuildFavor; - itbs.augdistil = item->AugDistiller; - itbs.unknown3 = 0xffffffff; - itbs.unknown4 = 0; - itbs.no_pet = item->NoPet; - itbs.unknown5 = 0; - - itbs.potion_belt_enabled = item->PotionBelt; - itbs.potion_belt_slots = item->PotionBeltSlots; - itbs.stacksize = stackable ? item->StackSize : 0; - itbs.no_transfer = item->NoTransfer; - itbs.expendablearrow = item->ExpendableArrow; - - itbs.unknown8 = 0; - itbs.unknown9 = 0; - itbs.unknown10 = 0; - itbs.unknown11 = 0; - itbs.unknown12 = 0; - itbs.unknown13 = 0; - itbs.unknown14 = 0; - - ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); - - // Effect Structures Broken down to allow variable length strings for effect names - int32 effect_unknown = 0; - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); - RoF2::structs::ClickEffectStruct ices; - memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); - - ices.effect = item->Click.Effect; - ices.level2 = item->Click.Level2; - ices.type = item->Click.Type; - ices.level = item->Click.Level; - ices.max_charges = item->MaxCharges; - ices.cast_time = item->CastTime; - ices.recast = item->RecastDelay; - ices.recast_type = item->RecastType; - - ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); - - if (strlen(item->ClickName) > 0) - { - ss.write((const char*)item->ClickName, strlen(item->ClickName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); - RoF2::structs::ProcEffectStruct ipes; - memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); - - ipes.effect = item->Proc.Effect; - ipes.level2 = item->Proc.Level2; - ipes.type = item->Proc.Type; - ipes.level = item->Proc.Level; - ipes.procrate = item->ProcRate; - - ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); - - if (strlen(item->ProcName) > 0) - { - ss.write((const char*)item->ProcName, strlen(item->ProcName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); - RoF2::structs::WornEffectStruct iwes; - memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); - - iwes.effect = item->Worn.Effect; - iwes.level2 = item->Worn.Level2; - iwes.type = item->Worn.Type; - iwes.level = item->Worn.Level; - - ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); - - if (strlen(item->WornName) > 0) - { - ss.write((const char*)item->WornName, strlen(item->WornName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - - RoF2::structs::WornEffectStruct ifes; - memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); - - ifes.effect = item->Focus.Effect; - ifes.level2 = item->Focus.Level2; - ifes.type = item->Focus.Type; - ifes.level = item->Focus.Level; - - ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); - - if (strlen(item->FocusName) > 0) - { - ss.write((const char*)item->FocusName, strlen(item->FocusName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - - RoF2::structs::WornEffectStruct ises; - memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); - - ises.effect = item->Scroll.Effect; - ises.level2 = item->Scroll.Level2; - ises.type = item->Scroll.Type; - ises.level = item->Scroll.Level; - - ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); - - if (strlen(item->ScrollName) > 0) - { - ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); - ss.write((const char*)&null_term, sizeof(uint8)); - } - else - { - ss.write((const char*)&null_term, sizeof(uint8)); - } - - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - - // Bard Effect? - RoF2::structs::WornEffectStruct ibes; - memset(&ibes, 0, sizeof(RoF2::structs::WornEffectStruct)); - - ibes.effect = item->Bard.Effect; - ibes.level2 = item->Bard.Level2; - ibes.type = item->Bard.Type; - ibes.level = item->Bard.Level; - //ibes.unknown6 = 0xffffffff; - - ss.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)); - } - else */ - ss.write((const char*)&null_term, sizeof(uint8)); - - ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 - // End of Effects - - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - RoF2::structs::ItemQuaternaryBodyStruct iqbs; - memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - - iqbs.scriptfileid = item->ScriptFileID; - iqbs.quest_item = item->QuestItemFlag; - iqbs.Power = 0; - iqbs.Purity = item->Purity; - iqbs.unknown16 = 0; - iqbs.BackstabDmg = item->BackstabDmg; - iqbs.DSMitigation = item->DSMitigation; - iqbs.HeroicStr = item->HeroicStr; - iqbs.HeroicInt = item->HeroicInt; - iqbs.HeroicWis = item->HeroicWis; - iqbs.HeroicAgi = item->HeroicAgi; - iqbs.HeroicDex = item->HeroicDex; - iqbs.HeroicSta = item->HeroicSta; - iqbs.HeroicCha = item->HeroicCha; - iqbs.HeroicMR = item->HeroicMR; - iqbs.HeroicFR = item->HeroicFR; - iqbs.HeroicCR = item->HeroicCR; - iqbs.HeroicDR = item->HeroicDR; - iqbs.HeroicPR = item->HeroicPR; - iqbs.HeroicSVCorrup = item->HeroicSVCorrup; - iqbs.HealAmt = item->HealAmt; - iqbs.SpellDmg = item->SpellDmg; - iqbs.clairvoyance = item->Clairvoyance; - - //unknown18; //Power Source Capacity or evolve filename? - //evolve_string; // Some String, but being evolution related is just a guess - - iqbs.Heirloom = 0; - iqbs.Placeable = 0; - - iqbs.unknown28 = -1; - iqbs.unknown30 = -1; - - iqbs.NoZone = 0; - iqbs.NoGround = 0; - iqbs.unknown37a = 0; // (guessed position) New to RoF2 - iqbs.unknown38 = 0; - - iqbs.unknown39 = 1; - - iqbs.subitem_count = 0; - - char *SubSerializations[10]; // - - uint32 SubLengths[10]; - - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - - SubSerializations[x] = nullptr; - - const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); - - if (subitem) { - - int SubSlotNumber; - - iqbs.subitem_count++; - - if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? - //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); - SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); - else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) - //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); - else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) - //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); - SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); - else - SubSlotNumber = slot_id_in; // ??????? - - /* - // TEST CODE: - SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); - */ - - SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); - } - } - - ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); - - for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { - - if (SubSerializations[x]) { - - ss.write((const char*)&x, sizeof(uint32)); - - ss.write(SubSerializations[x], SubLengths[x]); - - safe_delete_array(SubSerializations[x]); - } - } - - char* item_serial = new char[ss.tellp()]; - memset(item_serial, 0, ss.tellp()); - memcpy(item_serial, ss.str().c_str(), ss.tellp()); - - *length = ss.tellp(); - return item_serial; - } + //char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type) + //{ + // int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType); + // uint8 null_term = 0; + // bool stackable = inst->IsStackable(); + // uint32 merchant_slot = inst->GetMerchantSlot(); + // uint32 charges = inst->GetCharges(); + // if (!stackable && charges > 254) + // charges = 0xFFFFFFFF; + // + // std::stringstream ss(std::stringstream::in | std::stringstream::out | std::stringstream::binary); + // + // const ItemData *item = inst->GetUnscaledItem(); + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name); + // + // RoF2::structs::ItemSerializationHeader hdr; + // + // //sprintf(hdr.unknown000, "06e0002Y1W00"); + // + // snprintf(hdr.tracking_id, sizeof(hdr.tracking_id), "%016d", item->ID); + // + // hdr.stacksize = stackable ? charges : 1; + // hdr.unknown004 = 0; + // + // structs::ItemSlotStruct slot_id = ServerToRoF2Slot(slot_id_in, packet_type); + // + // hdr.slot_type = (merchant_slot == 0) ? slot_id.SlotType : 9; // 9 is merchant 20 is reclaim items? + // hdr.main_slot = (merchant_slot == 0) ? slot_id.MainSlot : merchant_slot; + // hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubSlot : 0xffff; + // hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugSlot : 0xffff; + // hdr.price = inst->GetPrice(); + // hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount(); + // hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0; + // hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot; + // hdr.unknown028 = 0; + // hdr.last_cast_time = inst->GetRecastTimestamp(); + // hdr.charges = (stackable ? (item->MaxCharges ? 1 : 0) : charges); + // hdr.inst_nodrop = inst->IsAttuned() ? 1 : 0; + // hdr.unknown044 = 0; + // hdr.unknown048 = 0; + // hdr.unknown052 = 0; + // hdr.isEvolving = item->EvolvingLevel > 0 ? 1 : 0; + // ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader)); + // + // if (item->EvolvingLevel > 0) { + // RoF2::structs::EvolvingItem evotop; + // evotop.unknown001 = 0; + // evotop.unknown002 = 0; + // evotop.unknown003 = 0; + // evotop.unknown004 = 0; + // evotop.evoLevel = item->EvolvingLevel; + // evotop.progress = 95.512; + // evotop.Activated = 1; + // evotop.evomaxlevel = 7; + // ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem)); + // } + // //ORNAMENT IDFILE / ICON + // uint32 ornaIcon = 0; + // uint32 heroModel = 0; + // + // if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) + // { + // char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); + // //Mainhand + // ss.write(tmp, strlen(tmp)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // //Offhand + // ss.write(tmp, strlen(tmp)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // ornaIcon = inst->GetOrnamentationIcon(); + // heroModel = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation + // ss.write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation + // } + // + // RoF2::structs::ItemSerializationHeaderFinish hdrf; + // hdrf.ornamentIcon = ornaIcon; + // hdrf.unknowna1 = 0xffffffff; + // hdrf.ornamentHeroModel = heroModel; + // hdrf.unknown063 = 0; + // hdrf.Copied = 0; + // hdrf.unknowna4 = 0xffffffff; + // hdrf.unknowna5 = 0; + // hdrf.ItemClass = item->ItemClass; + // + // ss.write((const char*)&hdrf, sizeof(RoF2::structs::ItemSerializationHeaderFinish)); + // + // if (strlen(item->Name) > 0) + // { + // ss.write(item->Name, strlen(item->Name)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // if (strlen(item->Lore) > 0) + // { + // ss.write(item->Lore, strlen(item->Lore)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // if (strlen(item->IDFile) > 0) + // { + // ss.write(item->IDFile, strlen(item->IDFile)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&null_term, sizeof(uint8)); + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct)); + // RoF2::structs::ItemBodyStruct ibs; + // memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct)); + // + // ibs.id = item->ID; + // ibs.weight = item->Weight; + // ibs.norent = item->NoRent; + // ibs.nodrop = item->NoDrop; + // ibs.attune = item->Attuneable; + // ibs.size = item->Size; + // ibs.slots = SwapBits21and22(item->Slots); + // ibs.price = item->Price; + // ibs.icon = item->Icon; + // ibs.unknown1 = 1; + // ibs.unknown2 = 1; + // ibs.BenefitFlag = item->BenefitFlag; + // ibs.tradeskills = item->Tradeskills; + // ibs.CR = item->CR; + // ibs.DR = item->DR; + // ibs.PR = item->PR; + // ibs.MR = item->MR; + // ibs.FR = item->FR; + // ibs.SVCorruption = item->SVCorruption; + // ibs.AStr = item->AStr; + // ibs.ASta = item->ASta; + // ibs.AAgi = item->AAgi; + // ibs.ADex = item->ADex; + // ibs.ACha = item->ACha; + // ibs.AInt = item->AInt; + // ibs.AWis = item->AWis; + // + // ibs.HP = item->HP; + // ibs.Mana = item->Mana; + // ibs.Endur = item->Endur; + // ibs.AC = item->AC; + // ibs.regen = item->Regen; + // ibs.mana_regen = item->ManaRegen; + // ibs.end_regen = item->EnduranceRegen; + // ibs.Classes = item->Classes; + // ibs.Races = item->Races; + // ibs.Deity = item->Deity; + // ibs.SkillModValue = item->SkillModValue; + // ibs.SkillModMax = 0xffffffff; + // ibs.SkillModType = (int8)(item->SkillModType); + // ibs.SkillModExtra = 0; + // ibs.BaneDmgRace = item->BaneDmgRace; + // ibs.BaneDmgBody = item->BaneDmgBody; + // ibs.BaneDmgRaceAmt = item->BaneDmgRaceAmt; + // ibs.BaneDmgAmt = item->BaneDmgAmt; + // ibs.Magic = item->Magic; + // ibs.CastTime_ = item->CastTime_; + // ibs.ReqLevel = item->ReqLevel; + // if (item->ReqLevel > 100) + // ibs.ReqLevel = 100; + // ibs.RecLevel = item->RecLevel; + // if (item->RecLevel > 100) + // ibs.RecLevel = 100; + // ibs.RecSkill = item->RecSkill; + // ibs.BardType = item->BardType; + // ibs.BardValue = item->BardValue; + // ibs.Light = item->Light; + // ibs.Delay = item->Delay; + // ibs.ElemDmgType = item->ElemDmgType; + // ibs.ElemDmgAmt = item->ElemDmgAmt; + // ibs.Range = item->Range; + // ibs.Damage = item->Damage; + // ibs.Color = item->Color; + // ibs.Prestige = 0; + // ibs.ItemType = item->ItemType; + // ibs.Material = item->Material; + // ibs.MaterialUnknown1 = 0; + // ibs.EliteMaterial = item->EliteMaterial; + // ibs.HerosForgeModel = item->HerosForgeModel; + // ibs.MaterialUnknown2 = 0; + // ibs.SellRate = item->SellRate; + // ibs.CombatEffects = item->CombatEffects; + // ibs.Shielding = item->Shielding; + // ibs.StunResist = item->StunResist; + // ibs.StrikeThrough = item->StrikeThrough; + // ibs.ExtraDmgSkill = item->ExtraDmgSkill; + // ibs.ExtraDmgAmt = item->ExtraDmgAmt; + // ibs.SpellShield = item->SpellShield; + // ibs.Avoidance = item->Avoidance; + // ibs.Accuracy = item->Accuracy; + // ibs.CharmFileID = item->CharmFileID; + // ibs.FactionAmt1 = item->FactionAmt1; + // ibs.FactionMod1 = item->FactionMod1; + // ibs.FactionAmt2 = item->FactionAmt2; + // ibs.FactionMod2 = item->FactionMod2; + // ibs.FactionAmt3 = item->FactionAmt3; + // ibs.FactionMod3 = item->FactionMod3; + // ibs.FactionAmt4 = item->FactionAmt4; + // ibs.FactionMod4 = item->FactionMod4; + // + // ss.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((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + // RoF2::structs::ItemSecondaryBodyStruct isbs; + // memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + // + // isbs.augtype = item->AugType; + // isbs.augrestrict2 = -1; + // isbs.augrestrict = item->AugRestrict; + // + // for (int x = AUG_BEGIN; x < consts::ITEM_COMMON_SIZE; x++) + // { + // isbs.augslots[x].type = item->AugSlotType[x]; + // isbs.augslots[x].visible = item->AugSlotVisible[x]; + // isbs.augslots[x].unknown = item->AugSlotUnk2[x]; + // } + // + // isbs.ldonpoint_type = item->PointType; + // isbs.ldontheme = item->LDoNTheme; + // isbs.ldonprice = item->LDoNPrice; + // isbs.ldonsellbackrate = item->LDoNSellBackRate; + // isbs.ldonsold = item->LDoNSold; + // + // isbs.bagtype = item->BagType; + // isbs.bagslots = item->BagSlots; + // isbs.bagsize = item->BagSize; + // isbs.wreduction = item->BagWR; + // + // isbs.book = item->Book; + // isbs.booktype = item->BookType; + // + // ss.write((const char*)&isbs, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); + // + // if (strlen(item->Filename) > 0) + // { + // ss.write((const char*)item->Filename, strlen(item->Filename)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + // RoF2::structs::ItemTertiaryBodyStruct itbs; + // memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + // + // itbs.loregroup = item->LoreGroup; + // itbs.artifact = item->ArtifactFlag; + // itbs.summonedflag = item->SummonedFlag; + // itbs.favor = item->Favor; + // itbs.fvnodrop = item->FVNoDrop; + // itbs.dotshield = item->DotShielding; + // itbs.atk = item->Attack; + // itbs.haste = item->Haste; + // itbs.damage_shield = item->DamageShield; + // itbs.guildfavor = item->GuildFavor; + // itbs.augdistil = item->AugDistiller; + // itbs.unknown3 = 0xffffffff; + // itbs.unknown4 = 0; + // itbs.no_pet = item->NoPet; + // itbs.unknown5 = 0; + // + // itbs.potion_belt_enabled = item->PotionBelt; + // itbs.potion_belt_slots = item->PotionBeltSlots; + // itbs.stacksize = stackable ? item->StackSize : 0; + // itbs.no_transfer = item->NoTransfer; + // itbs.expendablearrow = item->ExpendableArrow; + // + // itbs.unknown8 = 0; + // itbs.unknown9 = 0; + // itbs.unknown10 = 0; + // itbs.unknown11 = 0; + // itbs.unknown12 = 0; + // itbs.unknown13 = 0; + // itbs.unknown14 = 0; + // + // ss.write((const char*)&itbs, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); + // + // // Effect Structures Broken down to allow variable length strings for effect names + // int32 effect_unknown = 0; + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); + // RoF2::structs::ClickEffectStruct ices; + // memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); + // + // ices.effect = item->Click.Effect; + // ices.level2 = item->Click.Level2; + // ices.type = item->Click.Type; + // ices.level = item->Click.Level; + // ices.max_charges = item->MaxCharges; + // ices.cast_time = item->CastTime; + // ices.recast = item->RecastDelay; + // ices.recast_type = item->RecastType; + // + // ss.write((const char*)&ices, sizeof(RoF2::structs::ClickEffectStruct)); + // + // if (strlen(item->ClickName) > 0) + // { + // ss.write((const char*)item->ClickName, strlen(item->ClickName)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); + // RoF2::structs::ProcEffectStruct ipes; + // memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); + // + // ipes.effect = item->Proc.Effect; + // ipes.level2 = item->Proc.Level2; + // ipes.type = item->Proc.Type; + // ipes.level = item->Proc.Level; + // ipes.procrate = item->ProcRate; + // + // ss.write((const char*)&ipes, sizeof(RoF2::structs::ProcEffectStruct)); + // + // if (strlen(item->ProcName) > 0) + // { + // ss.write((const char*)item->ProcName, strlen(item->ProcName)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5 + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); + // RoF2::structs::WornEffectStruct iwes; + // memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); + // + // iwes.effect = item->Worn.Effect; + // iwes.level2 = item->Worn.Level2; + // iwes.type = item->Worn.Type; + // iwes.level = item->Worn.Level; + // + // ss.write((const char*)&iwes, sizeof(RoF2::structs::WornEffectStruct)); + // + // if (strlen(item->WornName) > 0) + // { + // ss.write((const char*)item->WornName, strlen(item->WornName)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // + // RoF2::structs::WornEffectStruct ifes; + // memset(&ifes, 0, sizeof(RoF2::structs::WornEffectStruct)); + // + // ifes.effect = item->Focus.Effect; + // ifes.level2 = item->Focus.Level2; + // ifes.type = item->Focus.Type; + // ifes.level = item->Focus.Level; + // + // ss.write((const char*)&ifes, sizeof(RoF2::structs::WornEffectStruct)); + // + // if (strlen(item->FocusName) > 0) + // { + // ss.write((const char*)item->FocusName, strlen(item->FocusName)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // + // RoF2::structs::WornEffectStruct ises; + // memset(&ises, 0, sizeof(RoF2::structs::WornEffectStruct)); + // + // ises.effect = item->Scroll.Effect; + // ises.level2 = item->Scroll.Level2; + // ises.type = item->Scroll.Type; + // ises.level = item->Scroll.Level; + // + // ss.write((const char*)&ises, sizeof(RoF2::structs::WornEffectStruct)); + // + // if (strlen(item->ScrollName) > 0) + // { + // ss.write((const char*)item->ScrollName, strlen(item->ScrollName)); + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // else + // { + // ss.write((const char*)&null_term, sizeof(uint8)); + // } + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // + // // Bard Effect? + // RoF2::structs::WornEffectStruct ibes; + // memset(&ibes, 0, sizeof(RoF2::structs::WornEffectStruct)); + // + // ibes.effect = item->Bard.Effect; + // ibes.level2 = item->Bard.Level2; + // ibes.type = item->Bard.Type; + // ibes.level = item->Bard.Level; + // //ibes.unknown6 = 0xffffffff; + // + // ss.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)); + // } + // else */ + // ss.write((const char*)&null_term, sizeof(uint8)); + // + // ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6 + // // End of Effects + // + // //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + // RoF2::structs::ItemQuaternaryBodyStruct iqbs; + // memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + // + // iqbs.scriptfileid = item->ScriptFileID; + // iqbs.quest_item = item->QuestItemFlag; + // iqbs.Power = 0; + // iqbs.Purity = item->Purity; + // iqbs.unknown16 = 0; + // iqbs.BackstabDmg = item->BackstabDmg; + // iqbs.DSMitigation = item->DSMitigation; + // iqbs.HeroicStr = item->HeroicStr; + // iqbs.HeroicInt = item->HeroicInt; + // iqbs.HeroicWis = item->HeroicWis; + // iqbs.HeroicAgi = item->HeroicAgi; + // iqbs.HeroicDex = item->HeroicDex; + // iqbs.HeroicSta = item->HeroicSta; + // iqbs.HeroicCha = item->HeroicCha; + // iqbs.HeroicMR = item->HeroicMR; + // iqbs.HeroicFR = item->HeroicFR; + // iqbs.HeroicCR = item->HeroicCR; + // iqbs.HeroicDR = item->HeroicDR; + // iqbs.HeroicPR = item->HeroicPR; + // iqbs.HeroicSVCorrup = item->HeroicSVCorrup; + // iqbs.HealAmt = item->HealAmt; + // iqbs.SpellDmg = item->SpellDmg; + // iqbs.clairvoyance = item->Clairvoyance; + // + // //unknown18; //Power Source Capacity or evolve filename? + // //evolve_string; // Some String, but being evolution related is just a guess + // + // iqbs.Heirloom = 0; + // iqbs.Placeable = 0; + // + // iqbs.unknown28 = -1; + // iqbs.unknown30 = -1; + // + // iqbs.NoZone = 0; + // iqbs.NoGround = 0; + // iqbs.unknown37a = 0; // (guessed position) New to RoF2 + // iqbs.unknown38 = 0; + // + // iqbs.unknown39 = 1; + // + // iqbs.subitem_count = 0; + // + // char *SubSerializations[10]; // + // + // uint32 SubLengths[10]; + // + // for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + // + // SubSerializations[x] = nullptr; + // + // const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x); + // + // if (subitem) { + // + // int SubSlotNumber; + // + // iqbs.subitem_count++; + // + // if (slot_id_in >= EmuConstants::GENERAL_BEGIN && slot_id_in <= EmuConstants::GENERAL_END) // (< 30) - no cursor? + // //SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1); + // SubSlotNumber = (((slot_id_in + 3) * EmuConstants::ITEM_CONTAINER_SIZE) + x + 1); + // else if (slot_id_in >= EmuConstants::BANK_BEGIN && slot_id_in <= EmuConstants::BANK_END) + // //SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1); + // SubSlotNumber = (((slot_id_in - EmuConstants::BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::BANK_BAGS_BEGIN + x); + // else if (slot_id_in >= EmuConstants::SHARED_BANK_BEGIN && slot_id_in <= EmuConstants::SHARED_BANK_END) + // //SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1); + // SubSlotNumber = (((slot_id_in - EmuConstants::SHARED_BANK_BEGIN) * EmuConstants::ITEM_CONTAINER_SIZE) + EmuConstants::SHARED_BANK_BAGS_BEGIN + x); + // else + // SubSlotNumber = slot_id_in; // ??????? + // + // /* + // // TEST CODE: + // SubSlotNumber = InventoryOld::CalcSlotID(slot_id_in, x); + // */ + // + // SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1, packet_type); + // } + // } + // + // ss.write((const char*)&iqbs, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); + // + // for (int x = SUB_BEGIN; x < EmuConstants::ITEM_CONTAINER_SIZE; ++x) { + // + // if (SubSerializations[x]) { + // + // ss.write((const char*)&x, sizeof(uint32)); + // + // ss.write(SubSerializations[x], SubLengths[x]); + // + // safe_delete_array(SubSerializations[x]); + // } + // } + // + // char* item_serial = new char[ss.tellp()]; + // memset(item_serial, 0, ss.tellp()); + // memcpy(item_serial, ss.str().c_str(), ss.tellp()); + // + // *length = ss.tellp(); + // return item_serial; + //} void SerializeItem(EQEmu::MemoryBuffer &packet_data, EQEmu::ItemInstance *inst, int container_id, int slot_id, int bag_id, int aug_id) { int ornamentation_augtype = RuleI(Character, OrnamentationAugmentType); @@ -5790,23 +5800,24 @@ namespace RoF2 uint32 orn_icon = 0; uint32 hero_model = 0; - //if(inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) - //{ - // char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile()); - // //Mainhand - // packet_data.Write(tmp, strlen(tmp)); - // packet_data.Write((const char*)&null_term, sizeof(uint8)); - // //Offhand - // ss.write(tmp, strlen(tmp)); - // ss.write((const char*)&null_term, sizeof(uint8)); - // orn_icon = inst->GetOrnamentationIcon(); - // hero_model = inst->GetOrnamentHeroModel(InventoryOld::CalcMaterialFromSlot(slot_id_in)); - //} - //else - //{ - packet_data.Write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation - packet_data.Write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation - //} + if(inst->GetOrnamentIDFile() && inst->GetOrnamentIcon()) + { + char tmp[30] = { 0 }; + sprintf(tmp, "IT%d", inst->GetOrnamentIDFile()); + //Mainhand + packet_data.Write(tmp, strlen(tmp)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); + //Offhand + packet_data.Write(tmp, strlen(tmp)); + packet_data.Write((const char*)&null_term, sizeof(uint8)); + orn_icon = inst->GetOrnamentIcon(); + hero_model = inst->GetOrnamentHeroModel(EQEmu::Inventory::CalcMaterialFromSlot(EQEmu::InventorySlot(container_id, slot_id))); + } + else + { + packet_data.Write((const char*)&null_term, sizeof(uint8)); // no main hand Ornamentation + packet_data.Write((const char*)&null_term, sizeof(uint8)); // no off hand Ornamentation + } RoF2::structs::ItemSerializationHeaderFinish hdrf; hdrf.ornamentIcon = orn_icon; @@ -5958,7 +5969,6 @@ namespace RoF2 packet_data.Write((const char*)&null_term, sizeof(uint8)); } - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF2::structs::ItemSecondaryBodyStruct)); RoF2::structs::ItemSecondaryBodyStruct isbs; memset(&isbs, 0, sizeof(RoF2::structs::ItemSecondaryBodyStruct)); @@ -5999,7 +6009,6 @@ namespace RoF2 packet_data.Write((const char*)&null_term, sizeof(uint8)); } - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF2::structs::ItemTertiaryBodyStruct)); RoF2::structs::ItemTertiaryBodyStruct itbs; memset(&itbs, 0, sizeof(RoF2::structs::ItemTertiaryBodyStruct)); @@ -6038,7 +6047,6 @@ namespace RoF2 // Effect Structures Broken down to allow variable length strings for effect names int32 effect_unknown = 0; - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Click effect struct is %i bytes", sizeof(RoF2::structs::ClickEffectStruct)); RoF2::structs::ClickEffectStruct ices; memset(&ices, 0, sizeof(RoF2::structs::ClickEffectStruct)); @@ -6065,7 +6073,6 @@ namespace RoF2 packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // clickunk7 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF2::structs::ProcEffectStruct)); RoF2::structs::ProcEffectStruct ipes; memset(&ipes, 0, sizeof(RoF2::structs::ProcEffectStruct)); @@ -6089,7 +6096,6 @@ namespace RoF2 packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown5 - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF2::structs::WornEffectStruct)); RoF2::structs::WornEffectStruct iwes; memset(&iwes, 0, sizeof(RoF2::structs::WornEffectStruct)); @@ -6173,7 +6179,6 @@ namespace RoF2 packet_data.Write((const char*)&effect_unknown, sizeof(int32)); // unknown6 // End of Effects - //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody Quaternary effect struct is %i bytes", sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); RoF2::structs::ItemQuaternaryBodyStruct iqbs; memset(&iqbs, 0, sizeof(RoF2::structs::ItemQuaternaryBodyStruct)); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index f67198b26..1c0abf90a 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -1265,14 +1265,14 @@ namespace SoD ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToSoDSlot(emu->from_slot); - eq->to_slot = ServerToSoDSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); + //ENCODE_LENGTH_EXACT(MoveItem_Struct); + //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //eq->from_slot = ServerToSoDSlot(emu->from_slot); + //eq->to_slot = ServerToSoDSlot(emu->to_slot); + //OUT(number_in_stack); + // + //FINISH_ENCODE(); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } @@ -3260,16 +3260,16 @@ namespace SoD DECODE(OP_MoveItem) { - DECODE_LENGTH_EXACT(structs::MoveItem_Struct); - SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - - Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot); - - emu->from_slot = SoDToServerSlot(eq->from_slot); - emu->to_slot = SoDToServerSlot(eq->to_slot); - IN(number_in_stack); - - FINISH_DIRECT_DECODE(); + //DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //Log.Out(Logs::General, Logs::Netcode, "[SoD] Moved item from %u to %u", eq->from_slot, eq->to_slot); + // + //emu->from_slot = SoDToServerSlot(eq->from_slot); + //emu->to_slot = SoDToServerSlot(eq->to_slot); + //IN(number_in_stack); + // + //FINISH_DIRECT_DECODE(); } DECODE(OP_PetCommands) diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index e6cf7e83d..47a45809f 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -930,14 +930,14 @@ namespace SoF ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToSoFSlot(emu->from_slot); - eq->to_slot = ServerToSoFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); + //ENCODE_LENGTH_EXACT(MoveItem_Struct); + //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //eq->from_slot = ServerToSoFSlot(emu->from_slot); + //eq->to_slot = ServerToSoFSlot(emu->to_slot); + //OUT(number_in_stack); + // + //FINISH_ENCODE(); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } @@ -2598,16 +2598,16 @@ namespace SoF DECODE(OP_MoveItem) { - DECODE_LENGTH_EXACT(structs::MoveItem_Struct); - SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - - Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot); - - emu->from_slot = SoFToServerSlot(eq->from_slot); - emu->to_slot = SoFToServerSlot(eq->to_slot); - IN(number_in_stack); - - FINISH_DIRECT_DECODE(); + //DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //Log.Out(Logs::General, Logs::Netcode, "[SoF] Moved item from %u to %u", eq->from_slot, eq->to_slot); + // + //emu->from_slot = SoFToServerSlot(eq->from_slot); + //emu->to_slot = SoFToServerSlot(eq->to_slot); + //IN(number_in_stack); + // + //FINISH_DIRECT_DECODE(); } DECODE(OP_PetCommands) diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index 8c3367697..fe7ab2067 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -778,14 +778,14 @@ namespace Titanium ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToTitaniumSlot(emu->from_slot); - eq->to_slot = ServerToTitaniumSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); + //ENCODE_LENGTH_EXACT(MoveItem_Struct); + //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //eq->from_slot = ServerToTitaniumSlot(emu->from_slot); + //eq->to_slot = ServerToTitaniumSlot(emu->to_slot); + //OUT(number_in_stack); + // + //FINISH_ENCODE(); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } @@ -1854,16 +1854,16 @@ namespace Titanium DECODE(OP_MoveItem) { - DECODE_LENGTH_EXACT(structs::MoveItem_Struct); - SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - - Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot); - - emu->from_slot = TitaniumToServerSlot(eq->from_slot); - emu->to_slot = TitaniumToServerSlot(eq->to_slot); - IN(number_in_stack); - - FINISH_DIRECT_DECODE(); + //DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //Log.Out(Logs::General, Logs::Netcode, "[Titanium] Moved item from %u to %u", eq->from_slot, eq->to_slot); + // + //emu->from_slot = TitaniumToServerSlot(eq->from_slot); + //emu->to_slot = TitaniumToServerSlot(eq->to_slot); + //IN(number_in_stack); + // + //FINISH_DIRECT_DECODE(); } DECODE(OP_PetCommands) diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 8a1754992..421a48d6a 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -1504,14 +1504,14 @@ namespace UF ENCODE(OP_MoveItem) { - ENCODE_LENGTH_EXACT(MoveItem_Struct); - SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); - - eq->from_slot = ServerToUFSlot(emu->from_slot); - eq->to_slot = ServerToUFSlot(emu->to_slot); - OUT(number_in_stack); - - FINISH_ENCODE(); + //ENCODE_LENGTH_EXACT(MoveItem_Struct); + //SETUP_DIRECT_ENCODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //eq->from_slot = ServerToUFSlot(emu->from_slot); + //eq->to_slot = ServerToUFSlot(emu->to_slot); + //OUT(number_in_stack); + // + //FINISH_ENCODE(); } ENCODE(OP_NewSpawn) { ENCODE_FORWARD(OP_ZoneSpawns); } @@ -3582,16 +3582,16 @@ namespace UF DECODE(OP_MoveItem) { - DECODE_LENGTH_EXACT(structs::MoveItem_Struct); - SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); - - Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot); - - emu->from_slot = UFToServerSlot(eq->from_slot); - emu->to_slot = UFToServerSlot(eq->to_slot); - IN(number_in_stack); - - FINISH_DIRECT_DECODE(); + //DECODE_LENGTH_EXACT(structs::MoveItem_Struct); + //SETUP_DIRECT_DECODE(MoveItem_Struct, structs::MoveItem_Struct); + // + //Log.Out(Logs::General, Logs::Netcode, "[UF] Moved item from %u to %u", eq->from_slot, eq->to_slot); + // + //emu->from_slot = UFToServerSlot(eq->from_slot); + //emu->to_slot = UFToServerSlot(eq->to_slot); + //IN(number_in_stack); + // + //FINISH_DIRECT_DECODE(); } DECODE(OP_PetCommands) diff --git a/tests/inventory_test.h b/tests/inventory_test.h index 3e25c1748..55ff1f655 100644 --- a/tests/inventory_test.h +++ b/tests/inventory_test.h @@ -175,7 +175,7 @@ private: void InventorySwapItemsTest() { - auto swap_result = inv.Swap(EQEmu::InventorySlot(0, 23), EQEmu::InventorySlot(0, 24)); + auto swap_result = inv.Swap(EQEmu::InventorySlot(0, 23), EQEmu::InventorySlot(0, 24), 0); TEST_ASSERT(swap_result == true); auto m_bag = inv.Get(EQEmu::InventorySlot(0, 24)); diff --git a/tests/memory_buffer_test.h b/tests/memory_buffer_test.h index db5df217e..9d6c0cec7 100644 --- a/tests/memory_buffer_test.h +++ b/tests/memory_buffer_test.h @@ -33,6 +33,7 @@ public: TEST_ADD(MemoryBufferTest::CopyTest); TEST_ADD(MemoryBufferTest::AssignTest); TEST_ADD(MemoryBufferTest::MoveTest); + TEST_ADD(MemoryBufferTest::SelfTest); TEST_ADD(MemoryBufferTest::ZeroTest); TEST_ADD(MemoryBufferTest::ClearTest); TEST_ADD(MemoryBufferTest::AddTest) @@ -449,6 +450,22 @@ private: TEST_ASSERT(data[26] == 0); } + void SelfTest() + { + EQEmu::MemoryBuffer mb2(mb); + void *addr = (void*)mb2; + + mb2 = mb2; + void *addr2 = (void*)mb2; + + TEST_ASSERT(addr != addr2); + + mb2 = std::move(mb2); + addr2 = (void*)mb2; + + TEST_ASSERT(addr2 != nullptr); + } + void ZeroTest() { mb.Zero(); diff --git a/zone/client.h b/zone/client.h index f17d99720..3d4e1c8d0 100644 --- a/zone/client.h +++ b/zone/client.h @@ -813,9 +813,9 @@ public: bool PushItemOnCursor(const ItemInst& inst, bool client_update = false); void SendCursorBuffer(); void DeleteItemInInventory(int16 slot_id, int8 quantity = 0, bool client_update = false, bool update_db = true); - bool SwapItem(MoveItem_Struct* move_in); - void SwapItemResync(MoveItem_Struct* move_slots); - void QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call = false); + bool SwapItem(MoveItemOld_Struct* move_in); + void SwapItemResync(MoveItemOld_Struct* move_slots); + void QSSwapItemAuditor(MoveItemOld_Struct* move_in, bool postaction_call = false); void PutLootInInventory(int16 slot_id, const ItemInst &inst, ServerLootItem_Struct** bag_item_data = 0); bool AutoPutLootInInventory(ItemInst& inst, bool try_worn = false, bool try_cursor = true, ServerLootItem_Struct** bag_item_data = 0); bool SummonItem(uint32 item_id, int16 charges = -1, uint32 aug1 = 0, uint32 aug2 = 0, uint32 aug3 = 0, uint32 aug4 = 0, uint32 aug5 = 0, uint32 aug6 = 0, bool attuned = false, uint16 to_slot = MainCursor, uint32 ornament_icon = 0, uint32 ornament_idfile = 0, uint32 ornament_hero_model = 0); diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 190a3e272..c49f3e035 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -9586,68 +9586,77 @@ void Client::Handle_OP_MoveItem(const EQApplicationPacket *app) { return; } - + if (app->size != sizeof(MoveItem_Struct)) { Log.Out(Logs::General, Logs::Error, "Wrong size: OP_MoveItem, size=%i, expected %i", app->size, sizeof(MoveItem_Struct)); return; } - + MoveItem_Struct* mi = (MoveItem_Struct*)app->pBuffer; - if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) - { - if (mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) - { - char *detect = nullptr; - const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); - const ItemInst *itm_to = GetInv().GetItem(mi->to_slot); - MakeAnyLenString(&detect, "Player issued a move item from %u(item id %u) to %u(item id %u) while casting %u.", - mi->from_slot, - itm_from ? itm_from->GetID() : 0, - mi->to_slot, - itm_to ? itm_to->GetID() : 0, - casting_spell_id); - database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName()); - safe_delete_array(detect); - Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots - return; - } - } + auto res = m_inventory.Swap(EQEmu::InventorySlot(mi->from_type, mi->from_slot, mi->from_bag_slot, mi->from_aug_slot), + EQEmu::InventorySlot(mi->to_type, mi->to_slot, mi->to_bag_slot, mi->to_aug_slot), + mi->number_in_stack); - // Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. - bool mi_hack = false; + //printf("%i %i %i %i --> %i %i %i %i (%u)\n", + // mi->from_type, mi->from_slot, mi->from_bag_slot, mi->from_aug_slot, + // mi->to_type, mi->to_slot, mi->to_bag_slot, mi->to_aug_slot, + // mi->number_in_stack); - if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) { - if (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } - else { - int16 from_parent = m_inv.CalcSlotId(mi->from_slot); - if (!m_inv[from_parent]) { mi_hack = true; } - else if (!m_inv[from_parent]->IsType(ItemClassContainer)) { mi_hack = true; } - else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; } - } - } - - if (mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) { - if (mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } - else { - int16 to_parent = m_inv.CalcSlotId(mi->to_slot); - if (!m_inv[to_parent]) { mi_hack = true; } - else if (!m_inv[to_parent]->IsType(ItemClassContainer)) { mi_hack = true; } - else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; } - } - } - - if (mi_hack) { Message(15, "Caution: Illegal use of inaccessible bag slots!"); } - - if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { - SwapItemResync(mi); - - bool error = false; - InterrogateInventory(this, false, true, false, error, false); - if (error) - InterrogateInventory(this, true, false, true, error); - } - - return; + //if (spellend_timer.Enabled() && casting_spell_id && !IsBardSong(casting_spell_id)) + //{ + // if (mi->from_slot != mi->to_slot && (mi->from_slot <= EmuConstants::GENERAL_END || mi->from_slot > 39) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) + // { + // char *detect = nullptr; + // const ItemInst *itm_from = GetInv().GetItem(mi->from_slot); + // const ItemInst *itm_to = GetInv().GetItem(mi->to_slot); + // MakeAnyLenString(&detect, "Player issued a move item from %u(item id %u) to %u(item id %u) while casting %u.", + // mi->from_slot, + // itm_from ? itm_from->GetID() : 0, + // mi->to_slot, + // itm_to ? itm_to->GetID() : 0, + // casting_spell_id); + // database.SetMQDetectionFlag(AccountName(), GetName(), detect, zone->GetShortName()); + // safe_delete_array(detect); + // Kick(); // Kick client to prevent client and server from getting out-of-sync inventory slots + // return; + // } + //} + // + //// Illegal bagslot usage checks. Currently, user only receives a message if this check is triggered. + //bool mi_hack = false; + // + //if (mi->from_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->from_slot <= EmuConstants::CURSOR_BAG_END) { + // if (mi->from_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } + // else { + // int16 from_parent = m_inv.CalcSlotId(mi->from_slot); + // if (!m_inv[from_parent]) { mi_hack = true; } + // else if (!m_inv[from_parent]->IsType(ItemClassContainer)) { mi_hack = true; } + // else if (m_inv.CalcBagIdx(mi->from_slot) >= m_inv[from_parent]->GetItem()->BagSlots) { mi_hack = true; } + // } + //} + // + //if (mi->to_slot >= EmuConstants::GENERAL_BAGS_BEGIN && mi->to_slot <= EmuConstants::CURSOR_BAG_END) { + // if (mi->to_slot >= EmuConstants::CURSOR_BAG_BEGIN) { mi_hack = true; } + // else { + // int16 to_parent = m_inv.CalcSlotId(mi->to_slot); + // if (!m_inv[to_parent]) { mi_hack = true; } + // else if (!m_inv[to_parent]->IsType(ItemClassContainer)) { mi_hack = true; } + // else if (m_inv.CalcBagIdx(mi->to_slot) >= m_inv[to_parent]->GetItem()->BagSlots) { mi_hack = true; } + // } + //} + // + //if (mi_hack) { Message(15, "Caution: Illegal use of inaccessible bag slots!"); } + // + //if (!SwapItem(mi) && IsValidSlot(mi->from_slot) && IsValidSlot(mi->to_slot)) { + // SwapItemResync(mi); + // + // bool error = false; + // InterrogateInventory(this, false, true, false, error, false); + // if (error) + // InterrogateInventory(this, true, false, true, error); + //} + // + //return; } void Client::Handle_OP_OpenContainer(const EQApplicationPacket *app) diff --git a/zone/command.cpp b/zone/command.cpp index 8581e36a9..fed5c7807 100644 --- a/zone/command.cpp +++ b/zone/command.cpp @@ -3119,77 +3119,77 @@ void command_listpetition(Client *c, const Seperator *sep) void command_equipitem(Client *c, const Seperator *sep) { - uint32 slot_id = atoi(sep->arg[1]); - if (sep->IsNumber(1) && ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource))) { - const ItemInst* from_inst = c->GetInv().GetItem(MainCursor); - const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) - bool partialmove = false; - int16 movecount; - - if (from_inst && from_inst->IsType(ItemClassCommon)) { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); - MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; - mi->from_slot = MainCursor; - mi->to_slot = slot_id; - // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking - - // crude stackable check to only 'move' the difference count on client instead of entire stack when applicable - if (to_inst && to_inst->IsStackable() && - (to_inst->GetItem()->ID == from_inst->GetItem()->ID) && - (to_inst->GetCharges() < to_inst->GetItem()->StackSize) && - (from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) { - movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges(); - mi->number_in_stack = (uint32)movecount; - partialmove = true; - } - else - mi->number_in_stack = from_inst->GetCharges(); - - // Save move changes - // Added conditional check to packet send..would have sent change even on a swap failure..whoops! - - if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below - // mi->number_in_stack is always from_inst->GetCharges() when partialmove is false - c->Message(13, "Error: Partial stack added to existing stack exceeds allowable stacksize"); - return; - } - else if(c->SwapItem(mi)) { - c->FastQueuePacket(&outapp); - - // if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance - - // below code has proper logic, but client does not like to have cursor charges changed - // (we could delete the cursor item and resend, but issues would arise if there are queued items) - //if (partialmove) { - // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); - // DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer; - // di->from_slot = SLOT_CURSOR; - // di->to_slot = 0xFFFFFFFF; - // di->number_in_stack = 0xFFFFFFFF; - - // c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete - - // for (int16 deletecount=0; deletecount < movecount; deletecount++) - // have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...) - // c->QueuePacket(outapp2); - - // safe_delete(outapp2); - //} - } - else { - c->Message(13, "Error: Unable to equip current item"); - } - safe_delete(outapp); - - // also send out a wear change packet? - } - else if (from_inst == nullptr) - c->Message(13, "Error: There is no item on your cursor"); - else - c->Message(13, "Error: Item on your cursor cannot be equipped"); - } - else - c->Message(0, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position"); +// uint32 slot_id = atoi(sep->arg[1]); +// if (sep->IsNumber(1) && ((slot_id >= EmuConstants::EQUIPMENT_BEGIN) && (slot_id <= EmuConstants::EQUIPMENT_END) || (slot_id == MainPowerSource))) { +// const ItemInst* from_inst = c->GetInv().GetItem(MainCursor); +// const ItemInst* to_inst = c->GetInv().GetItem(slot_id); // added (desync issue when forcing stack to stack) +// bool partialmove = false; +// int16 movecount; +// +// if (from_inst && from_inst->IsType(ItemClassCommon)) { +// EQApplicationPacket* outapp = new EQApplicationPacket(OP_MoveItem, sizeof(MoveItem_Struct)); +// MoveItem_Struct* mi = (MoveItem_Struct*)outapp->pBuffer; +// mi->from_slot = MainCursor; +// mi->to_slot = slot_id; +// // mi->number_in_stack = from_inst->GetCharges(); // replaced with con check for stacking +// +// // crude stackable check to only 'move' the difference count on client instead of entire stack when applicable +// if (to_inst && to_inst->IsStackable() && +// (to_inst->GetItem()->ID == from_inst->GetItem()->ID) && +// (to_inst->GetCharges() < to_inst->GetItem()->StackSize) && +// (from_inst->GetCharges() > to_inst->GetItem()->StackSize - to_inst->GetCharges())) { +// movecount = to_inst->GetItem()->StackSize - to_inst->GetCharges(); +// mi->number_in_stack = (uint32)movecount; +// partialmove = true; +// } +// else +// mi->number_in_stack = from_inst->GetCharges(); +// +// // Save move changes +// // Added conditional check to packet send..would have sent change even on a swap failure..whoops! +// +// if (partialmove) { // remove this con check if someone can figure out removing charges from cursor stack issue below +// // mi->number_in_stack is always from_inst->GetCharges() when partialmove is false +// c->Message(13, "Error: Partial stack added to existing stack exceeds allowable stacksize"); +// return; +// } +// else if(c->SwapItem(mi)) { +// c->FastQueuePacket(&outapp); +// +// // if the below code is still needed..just send an an item trade packet to each slot..it should overwrite the client instance +// +// // below code has proper logic, but client does not like to have cursor charges changed +// // (we could delete the cursor item and resend, but issues would arise if there are queued items) +// //if (partialmove) { +// // EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); +// // DeleteItem_Struct* di = (DeleteItem_Struct*)outapp2->pBuffer; +// // di->from_slot = SLOT_CURSOR; +// // di->to_slot = 0xFFFFFFFF; +// // di->number_in_stack = 0xFFFFFFFF; +// +// // c->Message(0, "Deleting %i charges from stack", movecount); // debug line..delete +// +// // for (int16 deletecount=0; deletecount < movecount; deletecount++) +// // have to use 'movecount' because mi->number_in_stack is 'ENCODED' at this point (i.e., 99 charges returns 22...) +// // c->QueuePacket(outapp2); +// +// // safe_delete(outapp2); +// //} +// } +// else { +// c->Message(13, "Error: Unable to equip current item"); +// } +// safe_delete(outapp); +// +// // also send out a wear change packet? +// } +// else if (from_inst == nullptr) +// c->Message(13, "Error: There is no item on your cursor"); +// else +// c->Message(13, "Error: Item on your cursor cannot be equipped"); +// } +// else +// c->Message(0, "Usage: #equipitem slotid[0-21] - equips the item on your cursor to the position"); } void command_zonelock(Client *c, const Seperator *sep) diff --git a/zone/inventory.cpp b/zone/inventory.cpp index 06eccd9c6..a23bd198e 100644 --- a/zone/inventory.cpp +++ b/zone/inventory.cpp @@ -716,122 +716,122 @@ void Client::SendCursorBuffer() // Remove item from inventory void Client::DeleteItemInInventory(int16 slot_id, int8 quantity, bool client_update, bool update_db) { - #if (EQDEBUG >= 5) - Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false"); - #endif - - // Added 'IsSlotValid(slot_id)' check to both segments of client packet processing. - // - cursor queue slots were slipping through and crashing client - if(!m_inv[slot_id]) { - // Make sure the client deletes anything in this slot to match the server. - if(client_update && IsValidSlot(slot_id)) { - EQApplicationPacket* outapp; - outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); - DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; - delitem->from_slot = slot_id; - delitem->to_slot = 0xFFFFFFFF; - delitem->number_in_stack = 0xFFFFFFFF; - QueuePacket(outapp); - safe_delete(outapp); - } - return; - } - - // start QS code - if(RuleB(QueryServ, PlayerLogDeletes)) { - uint16 delete_count = 0; - - if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } - - ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogDeletes, sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); - QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; - uint16 parent_offset = 0; - - qsaudit->char_id = character_id; - qsaudit->stack_size = quantity; - qsaudit->char_count = delete_count; - - qsaudit->items[parent_offset].char_slot = slot_id; - qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID(); - qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges(); - qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); - - if(m_inv[slot_id]->IsType(ItemClassContainer)) { - for(uint8 bag_idx = SUB_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { - ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); - - if(bagitem) { - int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx); - - qsaudit->items[++parent_offset].char_slot = bagslot_id; - qsaudit->items[parent_offset].item_id = bagitem->GetID(); - qsaudit->items[parent_offset].charges = bagitem->GetCharges(); - qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1); - qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2); - qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3); - qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4); - qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5); - } - } - } - - qspack->Deflate(); - if(worldserver.Connected()) { worldserver.SendPacket(qspack); } - safe_delete(qspack); - } - // end QS code - - bool isDeleted = m_inv.DeleteItem(slot_id, quantity); - - const ItemInst* inst = nullptr; - if (slot_id == MainCursor) { - auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); - if(update_db) - database.SaveCursor(character_id, s, e); - } - else { - // Save change to database - inst = m_inv[slot_id]; - if(update_db) - database.SaveInventory(character_id, inst, slot_id); - } - - if(client_update && IsValidSlot(slot_id)) { - EQApplicationPacket* outapp = nullptr; - if(inst) { - if (!inst->IsStackable() && !isDeleted) { - // Non stackable item with charges = Item with clicky spell effect ? Delete a charge. - outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct)); - } - else { - // Stackable, arrows, etc ? Delete one from the stack - outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct)); - } - - DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; - delitem->from_slot = slot_id; - delitem->to_slot = 0xFFFFFFFF; - delitem->number_in_stack = 0xFFFFFFFF; - - for(int loop=0;looppBuffer; - delitem->from_slot = slot_id; - delitem->to_slot = 0xFFFFFFFF; - delitem->number_in_stack = 0xFFFFFFFF; - - QueuePacket(outapp); - safe_delete(outapp); - } - } +// #if (EQDEBUG >= 5) +// Log.Out(Logs::General, Logs::None, "DeleteItemInInventory(%i, %i, %s)", slot_id, quantity, (client_update) ? "true":"false"); +// #endif +// +// // Added 'IsSlotValid(slot_id)' check to both segments of client packet processing. +// // - cursor queue slots were slipping through and crashing client +// if(!m_inv[slot_id]) { +// // Make sure the client deletes anything in this slot to match the server. +// if(client_update && IsValidSlot(slot_id)) { +// EQApplicationPacket* outapp; +// outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(DeleteItem_Struct)); +// DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; +// delitem->from_slot = slot_id; +// delitem->to_slot = 0xFFFFFFFF; +// delitem->number_in_stack = 0xFFFFFFFF; +// QueuePacket(outapp); +// safe_delete(outapp); +// } +// return; +// } +// +// // start QS code +// if(RuleB(QueryServ, PlayerLogDeletes)) { +// uint16 delete_count = 0; +// +// if(m_inv[slot_id]) { delete_count += m_inv.GetItem(slot_id)->GetTotalItemCount(); } +// +// ServerPacket* qspack = new ServerPacket(ServerOP_QSPlayerLogDeletes, sizeof(QSPlayerLogDelete_Struct) + (sizeof(QSDeleteItems_Struct) * delete_count)); +// QSPlayerLogDelete_Struct* qsaudit = (QSPlayerLogDelete_Struct*)qspack->pBuffer; +// uint16 parent_offset = 0; +// +// qsaudit->char_id = character_id; +// qsaudit->stack_size = quantity; +// qsaudit->char_count = delete_count; +// +// qsaudit->items[parent_offset].char_slot = slot_id; +// qsaudit->items[parent_offset].item_id = m_inv[slot_id]->GetID(); +// qsaudit->items[parent_offset].charges = m_inv[slot_id]->GetCharges(); +// qsaudit->items[parent_offset].aug_1 = m_inv[slot_id]->GetAugmentItemID(1); +// qsaudit->items[parent_offset].aug_2 = m_inv[slot_id]->GetAugmentItemID(2); +// qsaudit->items[parent_offset].aug_3 = m_inv[slot_id]->GetAugmentItemID(3); +// qsaudit->items[parent_offset].aug_4 = m_inv[slot_id]->GetAugmentItemID(4); +// qsaudit->items[parent_offset].aug_5 = m_inv[slot_id]->GetAugmentItemID(5); +// +// if(m_inv[slot_id]->IsType(ItemClassContainer)) { +// for(uint8 bag_idx = SUB_BEGIN; bag_idx < m_inv[slot_id]->GetItem()->BagSlots; bag_idx++) { +// ItemInst* bagitem = m_inv[slot_id]->GetItem(bag_idx); +// +// if(bagitem) { +// int16 bagslot_id = InventoryOld::CalcSlotId(slot_id, bag_idx); +// +// qsaudit->items[++parent_offset].char_slot = bagslot_id; +// qsaudit->items[parent_offset].item_id = bagitem->GetID(); +// qsaudit->items[parent_offset].charges = bagitem->GetCharges(); +// qsaudit->items[parent_offset].aug_1 = bagitem->GetAugmentItemID(1); +// qsaudit->items[parent_offset].aug_2 = bagitem->GetAugmentItemID(2); +// qsaudit->items[parent_offset].aug_3 = bagitem->GetAugmentItemID(3); +// qsaudit->items[parent_offset].aug_4 = bagitem->GetAugmentItemID(4); +// qsaudit->items[parent_offset].aug_5 = bagitem->GetAugmentItemID(5); +// } +// } +// } +// +// qspack->Deflate(); +// if(worldserver.Connected()) { worldserver.SendPacket(qspack); } +// safe_delete(qspack); +// } +// // end QS code +// +// bool isDeleted = m_inv.DeleteItem(slot_id, quantity); +// +// const ItemInst* inst = nullptr; +// if (slot_id == MainCursor) { +// auto s = m_inv.cursor_cbegin(), e = m_inv.cursor_cend(); +// if(update_db) +// database.SaveCursor(character_id, s, e); +// } +// else { +// // Save change to database +// inst = m_inv[slot_id]; +// if(update_db) +// database.SaveInventory(character_id, inst, slot_id); +// } +// +// if(client_update && IsValidSlot(slot_id)) { +// EQApplicationPacket* outapp = nullptr; +// if(inst) { +// if (!inst->IsStackable() && !isDeleted) { +// // Non stackable item with charges = Item with clicky spell effect ? Delete a charge. +// outapp = new EQApplicationPacket(OP_DeleteCharge, sizeof(MoveItem_Struct)); +// } +// else { +// // Stackable, arrows, etc ? Delete one from the stack +// outapp = new EQApplicationPacket(OP_DeleteItem, sizeof(MoveItem_Struct)); +// } +// +// DeleteItem_Struct* delitem = (DeleteItem_Struct*)outapp->pBuffer; +// delitem->from_slot = slot_id; +// delitem->to_slot = 0xFFFFFFFF; +// delitem->number_in_stack = 0xFFFFFFFF; +// +// for(int loop=0;looppBuffer; +// delitem->from_slot = slot_id; +// delitem->to_slot = 0xFFFFFFFF; +// delitem->number_in_stack = 0xFFFFFFFF; +// +// QueuePacket(outapp); +// safe_delete(outapp); +// } +// } } bool Client::PushItemOnCursor(const ItemInst& inst, bool client_update) @@ -1315,7 +1315,7 @@ bool Client::IsBankSlot(uint32 slot) // Moves items around both internally and in the database // In the future, this can be optimized by pushing all changes through one database REPLACE call -bool Client::SwapItem(MoveItem_Struct* move_in) { +bool Client::SwapItem(MoveItemOld_Struct* move_in) { uint32 src_slot_check = move_in->from_slot; uint32 dst_slot_check = move_in->to_slot; @@ -1788,7 +1788,7 @@ bool Client::SwapItem(MoveItem_Struct* move_in) { return true; } -void Client::SwapItemResync(MoveItem_Struct* move_slots) { +void Client::SwapItemResync(MoveItemOld_Struct* move_slots) { // wow..this thing created a helluva memory leak... // with any luck..this won't be needed in the future @@ -1883,7 +1883,7 @@ void Client::SwapItemResync(MoveItem_Struct* move_slots) { } } -void Client::QSSwapItemAuditor(MoveItem_Struct* move_in, bool postaction_call) { +void Client::QSSwapItemAuditor(MoveItemOld_Struct* move_in, bool postaction_call) { int16 from_slot_id = static_cast(move_in->from_slot); int16 to_slot_id = static_cast(move_in->to_slot); int16 move_amount = static_cast(move_in->number_in_stack); diff --git a/zone/trading.cpp b/zone/trading.cpp index b5bb3e42f..0af87625f 100644 --- a/zone/trading.cpp +++ b/zone/trading.cpp @@ -1333,68 +1333,68 @@ uint16 Client::FindTraderItem(int32 SerialNumber, uint16 Quantity){ } void Client::NukeTraderItem(uint16 Slot,int16 Charges,uint16 Quantity,Client* Customer,uint16 TraderSlot, int32 SerialNumber, int32 itemid) { - - if(!Customer) - return; - - Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity); - - if(Quantity < Charges) - { - Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber); - m_inv.DeleteItem(Slot, Quantity); - } - else - { - EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); - TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; - - tdis->Unknown000 = 0; - tdis->TraderID = Customer->GetID(); - if (Customer->GetClientVersion() >= ClientVersion::RoF) - { - // RoF+ use Item IDs for now - tdis->ItemID = itemid; - } - else - { - tdis->ItemID = SerialNumber; - } - tdis->Unknown012 = 0; - - - Customer->QueuePacket(outapp); - safe_delete(outapp); - - m_inv.DeleteItem(Slot); - } - // This updates the trader. Removes it from his trading bags. - // - const ItemInst* Inst = m_inv[Slot]; - - database.SaveInventory(CharacterID(), Inst, Slot); - - EQApplicationPacket* outapp2; - - if(Quantity < Charges) - outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); - else - outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); - - MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; - mis->from_slot = Slot; - mis->to_slot = 0xFFFFFFFF; - mis->number_in_stack = 0xFFFFFFFF; - - if(Quantity >= Charges) - Quantity = 1; - - for(int i = 0; i < Quantity; i++) { - - this->QueuePacket(outapp2); - } - safe_delete(outapp2); - +// +// if(!Customer) +// return; +// +// Log.Out(Logs::Detail, Logs::Trading, "NukeTraderItem(Slot %i, Charges %i, Quantity %i", Slot, Charges, Quantity); +// +// if(Quantity < Charges) +// { +// Customer->SendSingleTraderItem(this->CharacterID(), SerialNumber); +// m_inv.DeleteItem(Slot, Quantity); +// } +// else +// { +// EQApplicationPacket* outapp = new EQApplicationPacket(OP_TraderDelItem,sizeof(TraderDelItem_Struct)); +// TraderDelItem_Struct* tdis = (TraderDelItem_Struct*)outapp->pBuffer; +// +// tdis->Unknown000 = 0; +// tdis->TraderID = Customer->GetID(); +// if (Customer->GetClientVersion() >= ClientVersion::RoF) +// { +// // RoF+ use Item IDs for now +// tdis->ItemID = itemid; +// } +// else +// { +// tdis->ItemID = SerialNumber; +// } +// tdis->Unknown012 = 0; +// +// +// Customer->QueuePacket(outapp); +// safe_delete(outapp); +// +// m_inv.DeleteItem(Slot); +// } +// // This updates the trader. Removes it from his trading bags. +// // +// const ItemInst* Inst = m_inv[Slot]; +// +// database.SaveInventory(CharacterID(), Inst, Slot); +// +// EQApplicationPacket* outapp2; +// +// if(Quantity < Charges) +// outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); +// else +// outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); +// +// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; +// mis->from_slot = Slot; +// mis->to_slot = 0xFFFFFFFF; +// mis->number_in_stack = 0xFFFFFFFF; +// +// if(Quantity >= Charges) +// Quantity = 1; +// +// for(int i = 0; i < Quantity; i++) { +// +// this->QueuePacket(outapp2); +// } +// safe_delete(outapp2); +// } void Client::TraderUpdate(uint16 SlotID,uint32 TraderID){ // This method is no longer used. @@ -2507,347 +2507,347 @@ void Client::ShowBuyLines(const EQApplicationPacket *app) { } void Client::SellToBuyer(const EQApplicationPacket *app) { - - char* Buf = (char *)app->pBuffer; - - char ItemName[64]; - - /*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf); - uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf); - uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf); - uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); - uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf); - /* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf); - /*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf); - UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); - uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf); - /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused - - const ItemData *item = database.GetItem(ItemID); - - if(!item || !Quantity || !Price || !QtyBuyerWants) return; - - if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) { - Message(13, "You do not have %i %s on you.", Quantity, item->Name); - return; - } - - - Client *Buyer = entity_list.GetClientByID(BuyerID); - - if(!Buyer || !Buyer->IsBuyer()) { - Message(13, "The Buyer has gone away."); - return; - } - - // For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in - // the buyer inventory. - if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) { - Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name); - return; - } - - if((static_cast(Quantity) * static_cast(Price)) > MAX_TRANSACTION_VALUE) { - Message(13, "That would exceed the single transaction limit of %u platinum.", MAX_TRANSACTION_VALUE / 1000); - return; - } - - if(!Buyer->HasMoney(Quantity * Price)) { - Message(13, "The Buyer does not have sufficient money to purchase that quantity of %s.", item->Name); - Buyer->Message(13, "%s tried to sell you %i %s, but you have insufficient funds.", GetName(), Quantity, item->Name); - return; - } - - if(Buyer->CheckLoreConflict(item)) { - Message(13, "That item is LORE and the Buyer already has one."); - Buyer->Message(13, "%s tried to sell you %s but this item is LORE and you already have one.", - GetName(), item->Name); - return; - } - - if(item->NoDrop == 0) { - Message(13, "That item is NODROP."); - return; - } - - if(!item->Stackable) { - - for(uint32 i = 0; i < Quantity; i++) { - - int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); - - // This shouldn't happen, as we already checked there was space in the Buyer's inventory - if (SellerSlot == INVALID_INDEX) { - - if(i > 0) { - // Set the Quantity to the actual number we successfully transferred. - Quantity = i; - break; - } - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - return; - } - - ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); - - if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) { - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - - if(ItemToTransfer) - safe_delete(ItemToTransfer); - - return; - } - - database.SaveInventory(CharacterID(), 0, SellerSlot); - - safe_delete(ItemToTransfer); - - // Remove the item from inventory, clientside - // - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); - - MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; - mis->from_slot = SellerSlot; - mis->to_slot = 0xFFFFFFFF; - mis->number_in_stack = 0xFFFFFFFF; - - QueuePacket(outapp2); - safe_delete(outapp2); - - } - } - else { - // Stackable - // - uint32 QuantityMoved = 0; - - while(QuantityMoved < Quantity) { - - // Find the slot on the seller that has a stack of at least 1 of the item - int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); - - if (SellerSlot == INVALID_INDEX) { - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - return; - } - - ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); - - if(!ItemToTransfer) { - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - return; - } - - // If the stack we found has less than the quantity we are selling ... - if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) { - // Transfer the entire stack - - QuantityMoved += ItemToTransfer->GetCharges(); - - if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - safe_delete(ItemToTransfer); - return; - } - // Delete the entire stack from the seller's inventory - database.SaveInventory(CharacterID(), 0, SellerSlot); - - safe_delete(ItemToTransfer); - - // and tell the client to do the same. - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); - - MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; - mis->from_slot = SellerSlot; - mis->to_slot = 0xFFFFFFFF; - mis->number_in_stack = 0xFFFFFFFF; - - QueuePacket(outapp2); - safe_delete(outapp2); - } - else { - //Move the amount we need, and put the rest of the stack back in the seller's inventory - // - int QuantityToRemoveFromStack = Quantity - QuantityMoved; - - ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack); - - m_inv.PutItem(SellerSlot, *ItemToTransfer); - - database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot); - - ItemToTransfer->SetCharges(QuantityToRemoveFromStack); - - if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { - Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); - Message(13, "Internal error while processing transaction."); - safe_delete(ItemToTransfer); - return; - } - - safe_delete(ItemToTransfer); - - EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); - - MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; - mis->from_slot = SellerSlot; - mis->to_slot = 0xFFFFFFFF; - mis->number_in_stack = 0xFFFFFFFF; - - for(int i = 0; i < QuantityToRemoveFromStack; i++) - QueuePacket(outapp2); - - safe_delete(outapp2); - - QuantityMoved = Quantity; - } - } - - } - - Buyer->TakeMoneyFromPP(Quantity * Price); - - AddMoneyToPP(Quantity * Price, false); - - if(RuleB(Bazaar, AuditTrail)) - BazaarAuditTrail(GetName(), Buyer->GetName(), ItemName, Quantity, Quantity * Price, 1); - - // We now send a packet to the Seller, which causes it to display 'You have sold to for ' - // - // The PacketLength of 1016 is from the only instance of this packet I have seen, which is from Live, November 2008 - // The Titanium/6.2 struct is slightly different in that it appears to use fixed length strings instead of variable - // length as used on Live. The extra space in the packet is also likely to be used for Item compensation, if we ever - // implement that. - // - uint32 PacketLength = 1016; - - EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength); - - Buf = (char *)outapp->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); - - if(GetClientVersion() >= ClientVersion::SoD) - { - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price - } - - sprintf(Buf, "%s", Buyer->GetName()); Buf += 64; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); - - sprintf(Buf, "%s", ItemName); Buf += 64; - - QueuePacket(outapp); - - // This next packet goes to the Buyer and produces the 'You've bought from for ' - // - - Buf = (char *)outapp->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); - - if(Buyer->GetClientVersion() >= ClientVersion::SoD) - { - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price - } - - sprintf(Buf, "%s", GetName()); Buf += 64; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); - - sprintf(Buf, "%s", ItemName); Buf += 64; - - Buyer->QueuePacket(outapp); - - safe_delete(outapp); - - // Next we update the buyer table in the database to reflect the reduced quantity the Buyer wants to buy. - // - database.UpdateBuyLine(Buyer->CharacterID(), BuySlot, QtyBuyerWants - Quantity); - - // Next we update the Seller's Barter Window to reflect the reduced quantity the Buyer is now looking to buy. - // - EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_Barter, 936); - - Buf = (char *)outapp3->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown - VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID); - VARSTRUCT_ENCODE_STRING(Buf, ItemName); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); - - // If the amount we have just sold completely satisfies the quantity the Buyer was looking for, - // setting the next byte to 0 will remove the item from the Barter Window. - // - if(QtyBuyerWants - Quantity > 0) { - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On - } - else { - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On - } - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); - - VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); - - QueuePacket(outapp3); - safe_delete(outapp3); - - // The next packet updates the /buyer window with the reduced quantity, and toggles the buy line off if the - // quantity they wanted to buy has been met. - // - EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936); - - Buf = (char*)outapp4->pBuffer; - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); - VARSTRUCT_ENCODE_STRING(Buf, ItemName); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); - - if((QtyBuyerWants - Quantity) > 0) { - - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On - } - else { - VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On - } - - VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown - VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); - VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); - - Buyer->QueuePacket(outapp4); - safe_delete(outapp4); - - return; +// +// char* Buf = (char *)app->pBuffer; +// +// char ItemName[64]; +// +// /*uint32 Action =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused +// uint32 Quantity = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// uint32 BuyerID = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// uint32 BuySlot = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// uint32 UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); +// uint32 ItemID = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// /* ItemName */ VARSTRUCT_DECODE_STRING(ItemName, Buf); +// /*uint32 Unknown2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused +// uint32 QtyBuyerWants = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// UnknownByte = VARSTRUCT_DECODE_TYPE(uint8, Buf); +// uint32 Price = VARSTRUCT_DECODE_TYPE(uint32, Buf); +// /*uint32 BuyerID2 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused +// /*uint32 Unknown3 =*/ VARSTRUCT_SKIP_TYPE(uint32, Buf); //unused +// +// const ItemData *item = database.GetItem(ItemID); +// +// if(!item || !Quantity || !Price || !QtyBuyerWants) return; +// +// if (m_inv.HasItem(ItemID, Quantity, invWhereWorn | invWherePersonal | invWhereCursor) == INVALID_INDEX) { +// Message(13, "You do not have %i %s on you.", Quantity, item->Name); +// return; +// } +// +// +// Client *Buyer = entity_list.GetClientByID(BuyerID); +// +// if(!Buyer || !Buyer->IsBuyer()) { +// Message(13, "The Buyer has gone away."); +// return; +// } +// +// // For Stackable items, HasSpaceForItem will try check if there is space to stack with existing stacks in +// // the buyer inventory. +// if(!(Buyer->GetInv().HasSpaceForItem(item, Quantity))) { +// Message(13, "The Buyer does not have space for %i %s", Quantity, item->Name); +// return; +// } +// +// if((static_cast(Quantity) * static_cast(Price)) > MAX_TRANSACTION_VALUE) { +// Message(13, "That would exceed the single transaction limit of %u platinum.", MAX_TRANSACTION_VALUE / 1000); +// return; +// } +// +// if(!Buyer->HasMoney(Quantity * Price)) { +// Message(13, "The Buyer does not have sufficient money to purchase that quantity of %s.", item->Name); +// Buyer->Message(13, "%s tried to sell you %i %s, but you have insufficient funds.", GetName(), Quantity, item->Name); +// return; +// } +// +// if(Buyer->CheckLoreConflict(item)) { +// Message(13, "That item is LORE and the Buyer already has one."); +// Buyer->Message(13, "%s tried to sell you %s but this item is LORE and you already have one.", +// GetName(), item->Name); +// return; +// } +// +// if(item->NoDrop == 0) { +// Message(13, "That item is NODROP."); +// return; +// } +// +// if(!item->Stackable) { +// +// for(uint32 i = 0; i < Quantity; i++) { +// +// int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); +// +// // This shouldn't happen, as we already checked there was space in the Buyer's inventory +// if (SellerSlot == INVALID_INDEX) { +// +// if(i > 0) { +// // Set the Quantity to the actual number we successfully transferred. +// Quantity = i; +// break; +// } +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// return; +// } +// +// ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); +// +// if(!ItemToTransfer || !Buyer->MoveItemToInventory(ItemToTransfer, true)) { +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// +// if(ItemToTransfer) +// safe_delete(ItemToTransfer); +// +// return; +// } +// +// database.SaveInventory(CharacterID(), 0, SellerSlot); +// +// safe_delete(ItemToTransfer); +// +// // Remove the item from inventory, clientside +// // +// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); +// +// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; +// mis->from_slot = SellerSlot; +// mis->to_slot = 0xFFFFFFFF; +// mis->number_in_stack = 0xFFFFFFFF; +// +// QueuePacket(outapp2); +// safe_delete(outapp2); +// +// } +// } +// else { +// // Stackable +// // +// uint32 QuantityMoved = 0; +// +// while(QuantityMoved < Quantity) { +// +// // Find the slot on the seller that has a stack of at least 1 of the item +// int16 SellerSlot = m_inv.HasItem(ItemID, 1, invWhereWorn|invWherePersonal|invWhereCursor); +// +// if (SellerSlot == INVALID_INDEX) { +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// return; +// } +// +// ItemInst* ItemToTransfer = m_inv.PopItem(SellerSlot); +// +// if(!ItemToTransfer) { +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// return; +// } +// +// // If the stack we found has less than the quantity we are selling ... +// if(ItemToTransfer->GetCharges() <= (Quantity - QuantityMoved)) { +// // Transfer the entire stack +// +// QuantityMoved += ItemToTransfer->GetCharges(); +// +// if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// safe_delete(ItemToTransfer); +// return; +// } +// // Delete the entire stack from the seller's inventory +// database.SaveInventory(CharacterID(), 0, SellerSlot); +// +// safe_delete(ItemToTransfer); +// +// // and tell the client to do the same. +// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_MoveItem,sizeof(MoveItem_Struct)); +// +// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; +// mis->from_slot = SellerSlot; +// mis->to_slot = 0xFFFFFFFF; +// mis->number_in_stack = 0xFFFFFFFF; +// +// QueuePacket(outapp2); +// safe_delete(outapp2); +// } +// else { +// //Move the amount we need, and put the rest of the stack back in the seller's inventory +// // +// int QuantityToRemoveFromStack = Quantity - QuantityMoved; +// +// ItemToTransfer->SetCharges(ItemToTransfer->GetCharges() - QuantityToRemoveFromStack); +// +// m_inv.PutItem(SellerSlot, *ItemToTransfer); +// +// database.SaveInventory(CharacterID(), ItemToTransfer, SellerSlot); +// +// ItemToTransfer->SetCharges(QuantityToRemoveFromStack); +// +// if(!Buyer->MoveItemToInventory(ItemToTransfer, true)) { +// Log.Out(Logs::General, Logs::Error, "Unexpected error while moving item from seller to buyer."); +// Message(13, "Internal error while processing transaction."); +// safe_delete(ItemToTransfer); +// return; +// } +// +// safe_delete(ItemToTransfer); +// +// EQApplicationPacket* outapp2 = new EQApplicationPacket(OP_DeleteItem,sizeof(MoveItem_Struct)); +// +// MoveItem_Struct* mis = (MoveItem_Struct*)outapp2->pBuffer; +// mis->from_slot = SellerSlot; +// mis->to_slot = 0xFFFFFFFF; +// mis->number_in_stack = 0xFFFFFFFF; +// +// for(int i = 0; i < QuantityToRemoveFromStack; i++) +// QueuePacket(outapp2); +// +// safe_delete(outapp2); +// +// QuantityMoved = Quantity; +// } +// } +// +// } +// +// Buyer->TakeMoneyFromPP(Quantity * Price); +// +// AddMoneyToPP(Quantity * Price, false); +// +// if(RuleB(Bazaar, AuditTrail)) +// BazaarAuditTrail(GetName(), Buyer->GetName(), ItemName, Quantity, Quantity * Price, 1); +// +// // We now send a packet to the Seller, which causes it to display 'You have sold to for ' +// // +// // The PacketLength of 1016 is from the only instance of this packet I have seen, which is from Live, November 2008 +// // The Titanium/6.2 struct is slightly different in that it appears to use fixed length strings instead of variable +// // length as used on Live. The extra space in the packet is also likely to be used for Item compensation, if we ever +// // implement that. +// // +// uint32 PacketLength = 1016; +// +// EQApplicationPacket* outapp = new EQApplicationPacket(OP_Barter, PacketLength); +// +// Buf = (char *)outapp->pBuffer; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_SellerTransactionComplete); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); +// +// if(GetClientVersion() >= ClientVersion::SoD) +// { +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price +// } +// +// sprintf(Buf, "%s", Buyer->GetName()); Buf += 64; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); +// +// sprintf(Buf, "%s", ItemName); Buf += 64; +// +// QueuePacket(outapp); +// +// // This next packet goes to the Buyer and produces the 'You've bought from for ' +// // +// +// Buf = (char *)outapp->pBuffer; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerTransactionComplete); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Quantity * Price); +// +// if(Buyer->GetClientVersion() >= ClientVersion::SoD) +// { +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); // Think this is the upper 32 bits of a 64 bit price +// } +// +// sprintf(Buf, "%s", GetName()); Buf += 64; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0x01); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x00); +// +// sprintf(Buf, "%s", ItemName); Buf += 64; +// +// Buyer->QueuePacket(outapp); +// +// safe_delete(outapp); +// +// // Next we update the buyer table in the database to reflect the reduced quantity the Buyer wants to buy. +// // +// database.UpdateBuyLine(Buyer->CharacterID(), BuySlot, QtyBuyerWants - Quantity); +// +// // Next we update the Seller's Barter Window to reflect the reduced quantity the Buyer is now looking to buy. +// // +// EQApplicationPacket* outapp3 = new EQApplicationPacket(OP_Barter, 936); +// +// Buf = (char *)outapp3->pBuffer; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerInspectWindow); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // Unknown +// VARSTRUCT_ENCODE_TYPE(uint32, Buf,ItemID); +// VARSTRUCT_ENCODE_STRING(Buf, ItemName); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); +// +// // If the amount we have just sold completely satisfies the quantity the Buyer was looking for, +// // setting the next byte to 0 will remove the item from the Barter Window. +// // +// if(QtyBuyerWants - Quantity > 0) { +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On +// } +// else { +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On +// } +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Buyer->GetID()); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); +// +// VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); +// +// QueuePacket(outapp3); +// safe_delete(outapp3); +// +// // The next packet updates the /buyer window with the reduced quantity, and toggles the buy line off if the +// // quantity they wanted to buy has been met. +// // +// EQApplicationPacket* outapp4 = new EQApplicationPacket(OP_Barter, 936); +// +// Buf = (char*)outapp4->pBuffer; +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Barter_BuyerItemUpdate); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, BuySlot); +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, ItemID); +// VARSTRUCT_ENCODE_STRING(Buf, ItemName); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, item->Icon); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, QtyBuyerWants - Quantity); +// +// if((QtyBuyerWants - Quantity) > 0) { +// +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 1); // 0 = Toggle Off, 1 = Toggle On +// } +// else { +// VARSTRUCT_ENCODE_TYPE(uint8, Buf, 0); // 0 = Toggle Off, 1 = Toggle On +// } +// +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, Price); +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0x08f4); // Unknown +// VARSTRUCT_ENCODE_TYPE(uint32, Buf, 0); +// VARSTRUCT_ENCODE_STRING(Buf, Buyer->GetName()); +// +// Buyer->QueuePacket(outapp4); +// safe_delete(outapp4); +// +// return; } void Client::SendBuyerPacket(Client* Buyer) {