mirror of
https://github.com/EQEmu/Server.git
synced 2025-12-11 21:01:29 +00:00
Reworked client translators' SerializeItem() to recursive, single buffer methodology
This commit is contained in:
parent
de48d79b27
commit
37b84c4db1
@ -1,5 +1,8 @@
|
||||
EQEMu Changelog (Started on Sept 24, 2003 15:50)
|
||||
-------------------------------------------------------
|
||||
== 05/10/2016 ==
|
||||
Uleat: Converted client translators' 'SerializeItem()' to recursive, single buffer methodology. Titanium SerializeItem() now adds a null term between parent items instead of the invoking function
|
||||
|
||||
== 05/08/2016 ==
|
||||
Uleat: Re-coded Titanium client translator 'SerializeItem()' to use coded property assignments over file enumerated ones
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ namespace RoF
|
||||
static OpcodeManager *opcodes = nullptr;
|
||||
static Strategy struct_strategy;
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth);
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot);
|
||||
@ -531,70 +531,52 @@ namespace RoF
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
if (!in->size) {
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int item_count = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
ss.write((const char*)&item_count, sizeof(uint32));
|
||||
|
||||
uint32 Length = 0;
|
||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
std::string serialized = ss.str();
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -1505,29 +1487,37 @@ namespace RoF
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
//store away the emu struct
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
//ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0);
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
if (!serialized) {
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
in->size = length + 4;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized, length);
|
||||
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
safe_delete_array(serialized);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
@ -5190,53 +5180,43 @@ namespace RoF
|
||||
return NextItemInstSerialNumber;
|
||||
}
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
{
|
||||
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 Item_Struct *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
|
||||
|
||||
RoF::structs::ItemSerializationHeader hdr;
|
||||
|
||||
//sprintf(hdr.unknown000, "06e0002Y1W00");
|
||||
|
||||
snprintf(hdr.unknown000, sizeof(hdr.unknown000), "%016d", item->ID);
|
||||
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
|
||||
hdr.unknown004 = 0;
|
||||
|
||||
structs::InventorySlot_Struct slot_id = ServerToRoFSlot(slot_id_in);
|
||||
|
||||
hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items?
|
||||
hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot;
|
||||
hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff;
|
||||
hdr.unknown013 = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff;
|
||||
hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type);
|
||||
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
|
||||
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
|
||||
hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex);
|
||||
hdr.price = inst->GetPrice();
|
||||
hdr.merchant_slot = (merchant_slot == 0) ? 1 : inst->GetMerchantCount();
|
||||
//hdr.merchant_slot = (merchant_slot == 0) ? 1 : 0xffffffff;
|
||||
hdr.scaled_value = inst->IsScaling() ? inst->GetExp() / 100 : 0;
|
||||
hdr.instance_id = (merchant_slot == 0) ? inst->GetSerialNumber() : merchant_slot;
|
||||
hdr.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1);
|
||||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
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.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()));
|
||||
hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0);
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
|
||||
ss.write((const char*)&hdr, sizeof(RoF::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingItem > 0) {
|
||||
RoF::structs::EvolvingItem evotop;
|
||||
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
@ -5245,31 +5225,36 @@ namespace RoF
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
|
||||
ss.write((const char*)&evotop, sizeof(RoF::structs::EvolvingItem));
|
||||
}
|
||||
|
||||
//ORNAMENT IDFILE / ICON
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
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));
|
||||
if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in));
|
||||
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
|
||||
//Mainhand
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write("\0", 1);
|
||||
|
||||
//Offhand
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write("\0", 1);
|
||||
}
|
||||
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
|
||||
else {
|
||||
ss.write("\0", 1); // no main hand Ornamentation
|
||||
ss.write("\0", 1); // no off hand Ornamentation
|
||||
}
|
||||
|
||||
RoF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.unknowna1 = 0xffffffff;
|
||||
hdrf.ornamentHeroModel = heroModel;
|
||||
@ -5282,37 +5267,19 @@ namespace RoF
|
||||
ss.write((const char*)&hdrf, sizeof(RoF::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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("\0", 1);
|
||||
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF::structs::ItemBodyStruct));
|
||||
ss.write("\0", 1);
|
||||
|
||||
RoF::structs::ItemBodyStruct ibs;
|
||||
memset(&ibs, 0, sizeof(RoF::structs::ItemBodyStruct));
|
||||
|
||||
@ -5363,12 +5330,8 @@ namespace RoF
|
||||
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.ReqLevel = ((item->ReqLevel > 100) ? 100 : item->ReqLevel);
|
||||
ibs.RecLevel = ((item->RecLevel > 100) ? 100 : item->RecLevel);
|
||||
ibs.RecSkill = item->RecSkill;
|
||||
ibs.BardType = item->BardType;
|
||||
ibs.BardValue = item->BardValue;
|
||||
@ -5410,16 +5373,9 @@ namespace RoF
|
||||
|
||||
//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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody secondary struct is %i bytes", sizeof(RoF::structs::ItemSecondaryBodyStruct));
|
||||
RoF::structs::ItemSecondaryBodyStruct isbs;
|
||||
memset(&isbs, 0, sizeof(RoF::structs::ItemSecondaryBodyStruct));
|
||||
|
||||
@ -5427,11 +5383,10 @@ namespace RoF
|
||||
isbs.augdistiller = 65535;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
for (int x = AUG_INDEX_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];
|
||||
for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) {
|
||||
isbs.augslots[index].type = item->AugSlotType[index];
|
||||
isbs.augslots[index].visible = item->AugSlotVisible[index];
|
||||
isbs.augslots[index].unknown = item->AugSlotUnk2[index];
|
||||
}
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
@ -5451,16 +5406,9 @@ namespace RoF
|
||||
ss.write((const char*)&isbs, sizeof(RoF::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody tertiary struct is %i bytes", sizeof(RoF::structs::ItemTertiaryBodyStruct));
|
||||
RoF::structs::ItemTertiaryBodyStruct itbs;
|
||||
memset(&itbs, 0, sizeof(RoF::structs::ItemTertiaryBodyStruct));
|
||||
|
||||
@ -5482,7 +5430,7 @@ namespace RoF
|
||||
|
||||
itbs.potion_belt_enabled = item->PotionBelt;
|
||||
itbs.potion_belt_slots = item->PotionBeltSlots;
|
||||
itbs.stacksize = stackable ? item->StackSize : 0;
|
||||
itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0);
|
||||
itbs.no_transfer = item->NoTransfer;
|
||||
itbs.expendablearrow = item->ExpendableArrow;
|
||||
|
||||
@ -5499,7 +5447,6 @@ namespace RoF
|
||||
// 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(RoF::structs::ClickEffectStruct));
|
||||
RoF::structs::ClickEffectStruct ices;
|
||||
memset(&ices, 0, sizeof(RoF::structs::ClickEffectStruct));
|
||||
|
||||
@ -5515,18 +5462,11 @@ namespace RoF
|
||||
ss.write((const char*)&ices, sizeof(RoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody proc effect struct is %i bytes", sizeof(RoF::structs::ProcEffectStruct));
|
||||
RoF::structs::ProcEffectStruct ipes;
|
||||
memset(&ipes, 0, sizeof(RoF::structs::ProcEffectStruct));
|
||||
|
||||
@ -5539,18 +5479,11 @@ namespace RoF
|
||||
ss.write((const char*)&ipes, sizeof(RoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody worn effect struct is %i bytes", sizeof(RoF::structs::WornEffectStruct));
|
||||
RoF::structs::WornEffectStruct iwes;
|
||||
memset(&iwes, 0, sizeof(RoF::structs::WornEffectStruct));
|
||||
|
||||
@ -5562,14 +5495,8 @@ namespace RoF
|
||||
ss.write((const char*)&iwes, sizeof(RoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5584,14 +5511,8 @@ namespace RoF
|
||||
ss.write((const char*)&ifes, sizeof(RoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5606,14 +5527,8 @@ namespace RoF
|
||||
ss.write((const char*)&ises, sizeof(RoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5636,12 +5551,11 @@ namespace RoF
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
}
|
||||
else */
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ss.write("\0", 1);
|
||||
|
||||
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(RoF::structs::ItemQuaternaryBodyStruct));
|
||||
RoF::structs::ItemQuaternaryBodyStruct iqbs;
|
||||
memset(&iqbs, 0, sizeof(RoF::structs::ItemQuaternaryBodyStruct));
|
||||
|
||||
@ -5667,70 +5581,47 @@ namespace RoF
|
||||
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
|
||||
iqbs.HealAmt = item->HealAmt;
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
iqbs.clairvoyance = item->Clairvoyance;
|
||||
iqbs.Clairvoyance = item->Clairvoyance;
|
||||
iqbs.unknown28 = 0;
|
||||
iqbs.unknown30 = 0;
|
||||
iqbs.unknown39 = 1;
|
||||
|
||||
iqbs.subitem_count = 0;
|
||||
|
||||
char *SubSerializations[10]; // <watch>
|
||||
|
||||
uint32 SubLengths[10];
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::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 >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor?
|
||||
//SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1);
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x);
|
||||
else
|
||||
SubSlotNumber = slot_id_in; // ???????
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ss.write((const char*)&iqbs, sizeof(RoF::structs::ItemQuaternaryBodyStruct));
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) {
|
||||
std::stringstream::pos_type count_pos = ss.tellp();
|
||||
uint32 subitem_count = 0;
|
||||
|
||||
if (SubSerializations[x]) {
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.write((const char*)&x, sizeof(uint32));
|
||||
for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
ss.write(SubSerializations[x], SubLengths[x]);
|
||||
int SubSlotNumber = INVALID_INDEX;
|
||||
if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END)
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index);
|
||||
else
|
||||
SubSlotNumber = slot_id_in;
|
||||
|
||||
safe_delete_array(SubSerializations[x]);
|
||||
}
|
||||
ss.write((const char*)&index, sizeof(uint32));
|
||||
|
||||
SerializeItem(ss, sub, SubSlotNumber, (depth + 1));
|
||||
++subitem_count;
|
||||
}
|
||||
|
||||
char* item_serial = new char[ss.tellp()];
|
||||
memset(item_serial, 0, ss.tellp());
|
||||
memcpy(item_serial, ss.str().c_str(), ss.tellp());
|
||||
if (subitem_count) {
|
||||
std::stringstream::pos_type cur_pos = ss.tellp();
|
||||
ss.seekp(count_pos);
|
||||
|
||||
*length = ss.tellp();
|
||||
return item_serial;
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.seekp(cur_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static inline structs::InventorySlot_Struct ServerToRoFSlot(uint32 serverSlot)
|
||||
|
||||
@ -24,7 +24,7 @@ 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(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth, ItemPacketType packet_type);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType = ItemPacketInvalid);
|
||||
@ -602,70 +602,52 @@ namespace RoF2
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
if (!in->size) {
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int item_count = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
delete in;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
ss.write((const char*)&item_count, sizeof(uint32));
|
||||
|
||||
uint32 Length = 0;
|
||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0, ItemPacketCharInventory);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0, ItemPacketCharInventory);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
std::string serialized = ss.str();
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -1576,29 +1558,37 @@ namespace RoF2
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
//store away the emu struct
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0, old_item_pkt->PacketType);
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
if (!serialized) {
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0, old_item_pkt->PacketType);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
in->size = length + 4;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized, length);
|
||||
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
safe_delete_array(serialized);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
@ -5461,52 +5451,43 @@ namespace RoF2
|
||||
return NextItemInstSerialNumber;
|
||||
}
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth, ItemPacketType packet_type)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, 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 Item_Struct *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.unknown000, sizeof(hdr.unknown000), "%016d", item->ID);
|
||||
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
|
||||
hdr.unknown004 = 0;
|
||||
|
||||
structs::InventorySlot_Struct slot_id = ServerToRoF2Slot(slot_id_in, packet_type);
|
||||
|
||||
hdr.slot_type = (merchant_slot == 0) ? slot_id.Type : 9; // 9 is merchant 20 is reclaim items?
|
||||
hdr.main_slot = (merchant_slot == 0) ? slot_id.Slot : merchant_slot;
|
||||
hdr.sub_slot = (merchant_slot == 0) ? slot_id.SubIndex : 0xffff;
|
||||
hdr.aug_slot = (merchant_slot == 0) ? slot_id.AugIndex : 0xffff;
|
||||
hdr.slot_type = (inst->GetMerchantSlot() ? inventory::TypeMerchant : slot_id.Type);
|
||||
hdr.main_slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id.Slot);
|
||||
hdr.sub_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.SubIndex);
|
||||
hdr.aug_slot = (inst->GetMerchantSlot() ? 0xffff : slot_id.AugIndex);
|
||||
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.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1);
|
||||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
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.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()));
|
||||
hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0);
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
|
||||
ss.write((const char*)&hdr, sizeof(RoF2::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingItem > 0) {
|
||||
RoF2::structs::EvolvingItem evotop;
|
||||
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
@ -5515,31 +5496,36 @@ namespace RoF2
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
|
||||
ss.write((const char*)&evotop, sizeof(RoF2::structs::EvolvingItem));
|
||||
}
|
||||
|
||||
//ORNAMENT IDFILE / ICON
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
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));
|
||||
if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
heroModel = inst->GetOrnamentHeroModel(Inventory::CalcMaterialFromSlot(slot_id_in));
|
||||
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
|
||||
//Mainhand
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write("\0", 1);
|
||||
|
||||
//Offhand
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write("\0", 1);
|
||||
}
|
||||
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
|
||||
else {
|
||||
ss.write("\0", 1); // no main hand Ornamentation
|
||||
ss.write("\0", 1); // no off hand Ornamentation
|
||||
}
|
||||
|
||||
RoF2::structs::ItemSerializationHeaderFinish hdrf;
|
||||
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.unknowna1 = 0xffffffff;
|
||||
hdrf.ornamentHeroModel = heroModel;
|
||||
@ -5552,37 +5538,19 @@ namespace RoF2
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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("\0", 1);
|
||||
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] ItemBody struct is %i bytes", sizeof(RoF2::structs::ItemBodyStruct));
|
||||
ss.write("\0", 1);
|
||||
|
||||
RoF2::structs::ItemBodyStruct ibs;
|
||||
memset(&ibs, 0, sizeof(RoF2::structs::ItemBodyStruct));
|
||||
|
||||
@ -5633,12 +5601,8 @@ namespace RoF2
|
||||
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.ReqLevel = ((item->ReqLevel > 100) ? 100 : item->ReqLevel);
|
||||
ibs.RecLevel = ((item->RecLevel > 100) ? 100 : item->RecLevel);
|
||||
ibs.RecSkill = item->RecSkill;
|
||||
ibs.BardType = item->BardType;
|
||||
ibs.BardValue = item->BardValue;
|
||||
@ -5680,16 +5644,9 @@ namespace RoF2
|
||||
|
||||
//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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
//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));
|
||||
|
||||
@ -5697,11 +5654,10 @@ namespace RoF2
|
||||
isbs.augrestrict2 = -1;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
for (int x = AUG_INDEX_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];
|
||||
for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) {
|
||||
isbs.augslots[index].type = item->AugSlotType[index];
|
||||
isbs.augslots[index].visible = item->AugSlotVisible[index];
|
||||
isbs.augslots[index].unknown = item->AugSlotUnk2[index];
|
||||
}
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
@ -5721,16 +5677,9 @@ namespace RoF2
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
//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));
|
||||
|
||||
@ -5752,7 +5701,7 @@ namespace RoF2
|
||||
|
||||
itbs.potion_belt_enabled = item->PotionBelt;
|
||||
itbs.potion_belt_slots = item->PotionBeltSlots;
|
||||
itbs.stacksize = stackable ? item->StackSize : 0;
|
||||
itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0);
|
||||
itbs.no_transfer = item->NoTransfer;
|
||||
itbs.expendablearrow = item->ExpendableArrow;
|
||||
|
||||
@ -5769,7 +5718,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));
|
||||
|
||||
@ -5785,18 +5733,11 @@ namespace RoF2
|
||||
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("\0", 1);
|
||||
|
||||
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));
|
||||
|
||||
@ -5809,18 +5750,11 @@ namespace RoF2
|
||||
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("\0", 1);
|
||||
|
||||
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));
|
||||
|
||||
@ -5832,14 +5766,8 @@ namespace RoF2
|
||||
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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5854,14 +5782,8 @@ namespace RoF2
|
||||
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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5876,14 +5798,8 @@ namespace RoF2
|
||||
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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -5906,12 +5822,11 @@ namespace RoF2
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
}
|
||||
else */
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
|
||||
@ -5937,83 +5852,57 @@ namespace RoF2
|
||||
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
|
||||
iqbs.HealAmt = item->HealAmt;
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
iqbs.clairvoyance = item->Clairvoyance;
|
||||
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]; // <watch>
|
||||
|
||||
uint32 SubLengths[10];
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::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 >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor?
|
||||
//SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1);
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x);
|
||||
else
|
||||
SubSlotNumber = slot_id_in; // ???????
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::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_INDEX_BEGIN; x < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++x) {
|
||||
std::stringstream::pos_type count_pos = ss.tellp();
|
||||
uint32 subitem_count = 0;
|
||||
|
||||
if (SubSerializations[x]) {
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.write((const char*)&x, sizeof(uint32));
|
||||
for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
ss.write(SubSerializations[x], SubLengths[x]);
|
||||
int SubSlotNumber = INVALID_INDEX;
|
||||
if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END)
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index);
|
||||
else
|
||||
SubSlotNumber = slot_id_in;
|
||||
|
||||
safe_delete_array(SubSerializations[x]);
|
||||
}
|
||||
ss.write((const char*)&index, sizeof(uint32));
|
||||
|
||||
SerializeItem(ss, sub, SubSlotNumber, (depth + 1), packet_type);
|
||||
++subitem_count;
|
||||
}
|
||||
|
||||
char* item_serial = new char[ss.tellp()];
|
||||
memset(item_serial, 0, ss.tellp());
|
||||
memcpy(item_serial, ss.str().c_str(), ss.tellp());
|
||||
if (subitem_count) {
|
||||
std::stringstream::pos_type cur_pos = ss.tellp();
|
||||
ss.seekp(count_pos);
|
||||
|
||||
*length = ss.tellp();
|
||||
return item_serial;
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.seekp(cur_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static inline structs::InventorySlot_Struct ServerToRoF2Slot(uint32 serverSlot, ItemPacketType PacketType)
|
||||
|
||||
@ -4795,7 +4795,7 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 clairvoyance;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
@ -4833,7 +4833,6 @@ struct ItemQuaternaryBodyStruct
|
||||
uint8 unknown37a; // New to RoF2 - Probably variable length string
|
||||
uint8 unknown38; // 0
|
||||
uint8 unknown39; // 1
|
||||
uint32 subitem_count;
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
|
||||
@ -4530,7 +4530,7 @@ struct ItemSerializationHeader
|
||||
/*025*/ uint8 slot_type; // 0 = normal, 1 = bank, 2 = shared bank, 9 = merchant, 20 = ?
|
||||
/*026*/ uint16 main_slot;
|
||||
/*028*/ uint16 sub_slot;
|
||||
/*030*/ uint16 unknown013; // 0xffff
|
||||
/*030*/ uint16 aug_slot; // 0xffff
|
||||
/*032*/ uint32 price;
|
||||
/*036*/ uint32 merchant_slot; //1 if not a merchant item
|
||||
/*040*/ uint32 scaled_value; //0
|
||||
@ -4794,7 +4794,7 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 clairvoyance;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
@ -4821,7 +4821,6 @@ struct ItemQuaternaryBodyStruct
|
||||
uint32 unknown_RoF8;
|
||||
uint8 unknown38; // 0
|
||||
uint8 unknown39; // 1
|
||||
uint32 subitem_count;
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
|
||||
@ -22,7 +22,7 @@ namespace SoD
|
||||
static OpcodeManager *opcodes = nullptr;
|
||||
static Strategy struct_strategy;
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth);
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline uint32 ServerToSoDSlot(uint32 ServerSlot);
|
||||
@ -335,30 +335,23 @@ namespace SoD
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
if (!in->size) {
|
||||
in->size = 4;
|
||||
|
||||
in->pBuffer = new uchar[in->size];
|
||||
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int item_count = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
@ -366,39 +359,28 @@ namespace SoD
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
uint32 Length = 0;
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
ss.write((const char*)&item_count, sizeof(uint32));
|
||||
|
||||
if (Serialized) {
|
||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
std::string serialized = ss.str();
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -1036,29 +1018,37 @@ namespace SoD
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
//store away the emu struct
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
//ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0);
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
if (!serialized) {
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
in->size = length + 4;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized, length);
|
||||
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
safe_delete_array(serialized);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
@ -3550,34 +3540,26 @@ namespace SoD
|
||||
return NextItemInstSerialNumber;
|
||||
}
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
{
|
||||
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 Item_Struct *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
|
||||
SoD::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
|
||||
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
|
||||
hdr.unknown004 = 0;
|
||||
|
||||
int32 slot_id = ServerToSoDSlot(slot_id_in);
|
||||
|
||||
hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot;
|
||||
hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id);
|
||||
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.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1);
|
||||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
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.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()));
|
||||
hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0);
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
@ -3590,41 +3572,23 @@ namespace SoD
|
||||
ss.write((const char*)&hdr, sizeof(SoD::structs::ItemSerializationHeader));
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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("\0", 1);
|
||||
|
||||
SoD::structs::ItemBodyStruct ibs;
|
||||
memset(&ibs, 0, sizeof(SoD::structs::ItemBodyStruct));
|
||||
|
||||
ibs.id = item->ID;
|
||||
// weight is uint8 in the struct, and some weights exceed that, so capping at 255.
|
||||
ibs.weight = (item->Weight > 255) ? 255 : item->Weight;
|
||||
ibs.weight = ((item->Weight > 255) ? 255 : item->Weight);
|
||||
ibs.norent = item->NoRent;
|
||||
ibs.nodrop = item->NoDrop;
|
||||
ibs.attune = item->Attuneable;
|
||||
@ -3710,14 +3674,8 @@ namespace SoD
|
||||
|
||||
//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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
SoD::structs::ItemSecondaryBodyStruct isbs;
|
||||
memset(&isbs, 0, sizeof(SoD::structs::ItemSecondaryBodyStruct));
|
||||
@ -3725,11 +3683,10 @@ namespace SoD
|
||||
isbs.augtype = item->AugType;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
for (int x = 0; 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];
|
||||
for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) {
|
||||
isbs.augslots[index].type = item->AugSlotType[index];
|
||||
isbs.augslots[index].visible = item->AugSlotVisible[index];
|
||||
isbs.augslots[index].unknown = item->AugSlotUnk2[index];
|
||||
}
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
@ -3749,14 +3706,8 @@ namespace SoD
|
||||
ss.write((const char*)&isbs, sizeof(SoD::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
SoD::structs::ItemTertiaryBodyStruct itbs;
|
||||
memset(&itbs, 0, sizeof(SoD::structs::ItemTertiaryBodyStruct));
|
||||
@ -3776,7 +3727,7 @@ namespace SoD
|
||||
|
||||
itbs.potion_belt_enabled = item->PotionBelt;
|
||||
itbs.potion_belt_slots = item->PotionBeltSlots;
|
||||
itbs.stacksize = stackable ? item->StackSize : 0;
|
||||
itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0);
|
||||
itbs.no_transfer = item->NoTransfer;
|
||||
itbs.expendablearrow = item->ExpendableArrow;
|
||||
|
||||
@ -3800,14 +3751,8 @@ namespace SoD
|
||||
ss.write((const char*)&ices, sizeof(SoD::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7
|
||||
|
||||
@ -3823,14 +3768,8 @@ namespace SoD
|
||||
ss.write((const char*)&ipes, sizeof(SoD::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5
|
||||
|
||||
@ -3845,14 +3784,8 @@ namespace SoD
|
||||
ss.write((const char*)&iwes, sizeof(SoD::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -3867,14 +3800,8 @@ namespace SoD
|
||||
ss.write((const char*)&ifes, sizeof(SoD::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -3889,14 +3816,8 @@ namespace SoD
|
||||
ss.write((const char*)&ises, sizeof(SoD::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
// End of Effects
|
||||
@ -3926,67 +3847,44 @@ namespace SoD
|
||||
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
|
||||
iqbs.HealAmt = item->HealAmt;
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
iqbs.clairvoyance = item->Clairvoyance;
|
||||
|
||||
iqbs.subitem_count = 0;
|
||||
|
||||
char *SubSerializations[10]; // <watch>
|
||||
|
||||
uint32 SubLengths[10];
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::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 >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor?
|
||||
//SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1);
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x);
|
||||
else
|
||||
SubSlotNumber = slot_id_in; // ???????
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
iqbs.Clairvoyance = item->Clairvoyance;
|
||||
|
||||
ss.write((const char*)&iqbs, sizeof(SoD::structs::ItemQuaternaryBodyStruct));
|
||||
|
||||
for (int x = 0; x < 10; ++x) {
|
||||
std::stringstream::pos_type count_pos = ss.tellp();
|
||||
uint32 subitem_count = 0;
|
||||
|
||||
if (SubSerializations[x]) {
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.write((const char*)&x, sizeof(uint32));
|
||||
for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
ss.write(SubSerializations[x], SubLengths[x]);
|
||||
int SubSlotNumber = INVALID_INDEX;
|
||||
if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END)
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index);
|
||||
else
|
||||
SubSlotNumber = slot_id_in;
|
||||
|
||||
safe_delete_array(SubSerializations[x]);
|
||||
}
|
||||
ss.write((const char*)&index, sizeof(uint32));
|
||||
|
||||
SerializeItem(ss, sub, SubSlotNumber, (depth + 1));
|
||||
++subitem_count;
|
||||
}
|
||||
|
||||
char* item_serial = new char[ss.tellp()];
|
||||
memset(item_serial, 0, ss.tellp());
|
||||
memcpy(item_serial, ss.str().c_str(), ss.tellp());
|
||||
if (subitem_count) {
|
||||
std::stringstream::pos_type cur_pos = ss.tellp();
|
||||
ss.seekp(count_pos);
|
||||
|
||||
*length = ss.tellp();
|
||||
return item_serial;
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.seekp(cur_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32 ServerToSoDSlot(uint32 serverSlot)
|
||||
|
||||
@ -4184,10 +4184,9 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 clairvoyance;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint32 subitem_count;
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
|
||||
@ -22,7 +22,7 @@ namespace SoF
|
||||
static OpcodeManager *opcodes = nullptr;
|
||||
static Strategy struct_strategy;
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth);
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline uint32 ServerToSoFSlot(uint32 serverSlot);
|
||||
@ -317,26 +317,23 @@ namespace SoF
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
if (!in->size) {
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int item_count = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
@ -344,41 +341,28 @@ namespace SoF
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
ss.write((const char*)&item_count, sizeof(uint32));
|
||||
|
||||
uint32 Length = 0;
|
||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
|
||||
if (Serialized) {
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
std::string serialized = ss.str();
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -834,29 +818,37 @@ namespace SoF
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
//store away the emu struct
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
//ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0);
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
if (!serialized) {
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
in->size = length + 4;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized, length);
|
||||
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
safe_delete_array(serialized);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
@ -2873,34 +2865,26 @@ namespace SoF
|
||||
return NextItemInstSerialNumber;
|
||||
}
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
{
|
||||
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 Item_Struct *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
|
||||
SoF::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
|
||||
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
|
||||
hdr.unknown004 = 0;
|
||||
|
||||
int32 slot_id = ServerToSoFSlot(slot_id_in);
|
||||
|
||||
hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot;
|
||||
hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id);
|
||||
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.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1);
|
||||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
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.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()));
|
||||
hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0);
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
@ -2912,41 +2896,23 @@ namespace SoF
|
||||
ss.write((const char*)&hdr, sizeof(SoF::structs::ItemSerializationHeader));
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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("\0", 1);
|
||||
|
||||
SoF::structs::ItemBodyStruct ibs;
|
||||
memset(&ibs, 0, sizeof(SoF::structs::ItemBodyStruct));
|
||||
|
||||
ibs.id = item->ID;
|
||||
// weight is uint8 in the struct, and some weights exceed that, so capping at 255.
|
||||
ibs.weight = (item->Weight > 255) ? 255 : item->Weight;
|
||||
ibs.weight = ((item->Weight > 255) ? 255 : item->Weight);
|
||||
ibs.norent = item->NoRent;
|
||||
ibs.nodrop = item->NoDrop;
|
||||
ibs.attune = item->Attuneable;
|
||||
@ -3032,14 +2998,8 @@ namespace SoF
|
||||
|
||||
//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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
SoF::structs::ItemSecondaryBodyStruct isbs;
|
||||
memset(&isbs, 0, sizeof(SoF::structs::ItemSecondaryBodyStruct));
|
||||
@ -3047,11 +3007,10 @@ namespace SoF
|
||||
isbs.augtype = item->AugType;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
for (int x = 0; 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];
|
||||
for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) {
|
||||
isbs.augslots[index].type = item->AugSlotType[index];
|
||||
isbs.augslots[index].visible = item->AugSlotVisible[index];
|
||||
isbs.augslots[index].unknown = item->AugSlotUnk2[index];
|
||||
}
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
@ -3071,14 +3030,8 @@ namespace SoF
|
||||
ss.write((const char*)&isbs, sizeof(SoF::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
SoF::structs::ItemTertiaryBodyStruct itbs;
|
||||
memset(&itbs, 0, sizeof(SoF::structs::ItemTertiaryBodyStruct));
|
||||
@ -3098,7 +3051,7 @@ namespace SoF
|
||||
|
||||
itbs.potion_belt_enabled = item->PotionBelt;
|
||||
itbs.potion_belt_slots = item->PotionBeltSlots;
|
||||
itbs.stacksize = stackable ? item->StackSize : 0;
|
||||
itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0);
|
||||
itbs.no_transfer = item->NoTransfer;
|
||||
itbs.expendablearrow = item->ExpendableArrow;
|
||||
|
||||
@ -3122,14 +3075,8 @@ namespace SoF
|
||||
ss.write((const char*)&ices, sizeof(SoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7
|
||||
|
||||
@ -3145,14 +3092,8 @@ namespace SoF
|
||||
ss.write((const char*)&ipes, sizeof(SoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5
|
||||
|
||||
@ -3167,14 +3108,8 @@ namespace SoF
|
||||
ss.write((const char*)&iwes, sizeof(SoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -3189,14 +3124,8 @@ namespace SoF
|
||||
ss.write((const char*)&ifes, sizeof(SoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -3211,14 +3140,8 @@ namespace SoF
|
||||
ss.write((const char*)&ises, sizeof(SoF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
// End of Effects
|
||||
@ -3248,64 +3171,43 @@ namespace SoF
|
||||
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
|
||||
iqbs.HealAmt = item->HealAmt;
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
//iqbs.clairvoyance = item->Clairvoyance;
|
||||
|
||||
iqbs.subitem_count = 0;
|
||||
|
||||
char *SubSerializations[10]; // <watch>
|
||||
|
||||
uint32 SubLengths[10];
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::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 >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor?
|
||||
//SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1);
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x);
|
||||
else
|
||||
SubSlotNumber = slot_id_in; // ???????
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ss.write((const char*)&iqbs, sizeof(SoF::structs::ItemQuaternaryBodyStruct));
|
||||
|
||||
for (int x = 0; x < 10; ++x) {
|
||||
std::stringstream::pos_type count_pos = ss.tellp();
|
||||
uint32 subitem_count = 0;
|
||||
|
||||
if (SubSerializations[x]) {
|
||||
ss.write((const char*)&x, sizeof(uint32));
|
||||
ss.write(SubSerializations[x], SubLengths[x]);
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
safe_delete_array(SubSerializations[x]);
|
||||
}
|
||||
for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
int SubSlotNumber = INVALID_INDEX;
|
||||
if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END)
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index);
|
||||
else
|
||||
SubSlotNumber = slot_id_in;
|
||||
|
||||
ss.write((const char*)&index, sizeof(uint32));
|
||||
|
||||
SerializeItem(ss, sub, SubSlotNumber, (depth + 1));
|
||||
++subitem_count;
|
||||
}
|
||||
|
||||
char* item_serial = new char[ss.tellp()];
|
||||
memset(item_serial, 0, ss.tellp());
|
||||
memcpy(item_serial, ss.str().c_str(), ss.tellp());
|
||||
if (subitem_count) {
|
||||
std::stringstream::pos_type cur_pos = ss.tellp();
|
||||
ss.seekp(count_pos);
|
||||
|
||||
*length = ss.tellp();
|
||||
return item_serial;
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.seekp(cur_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32 ServerToSoFSlot(uint32 serverSlot)
|
||||
|
||||
@ -4039,7 +4039,6 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint32 subitem_count;
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
|
||||
@ -20,7 +20,7 @@ namespace Titanium
|
||||
static OpcodeManager *opcodes = nullptr;
|
||||
static Strategy struct_strategy;
|
||||
|
||||
std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth);
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline int16 ServerToTitaniumSlot(uint32 serverSlot);
|
||||
@ -260,11 +260,11 @@ namespace Titanium
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
@ -272,26 +272,25 @@ namespace Titanium
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
//do the transform...
|
||||
std::string serial_string;
|
||||
for (int r = 0; r < itemcount; r++, eq++) {
|
||||
std::string serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, 0); // assumed move operation: string& = string&&
|
||||
if (!serialized.empty()) {
|
||||
serial_string.append(serialized);
|
||||
serial_string.push_back('\0');
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
for (int r = 0; r < itemcount; r++, eq++) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
// do we need to account for a trailing null escape?
|
||||
in->size = serial_string.size();
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
memcpy(in->pBuffer, serial_string.c_str(), serial_string.size());
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
@ -716,27 +715,34 @@ namespace Titanium
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
//ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
std::string serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, 0); // assumed move operation: string& = string&&
|
||||
if (serialized.empty()) {
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
|
||||
in->size = serialized.size() + 5; // ItemPacketType + Serialization + \0
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized.c_str(), serialized.size());
|
||||
new_item_pkt->SerializedItem[serialized.size()] = '\0';
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
@ -2077,301 +2083,241 @@ namespace Titanium
|
||||
}
|
||||
|
||||
// file scope helper methods
|
||||
std::string SerializeItem(const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
{
|
||||
std::string serialization;
|
||||
const char* protection = "\\\\\\\\\\";
|
||||
const Item_Struct* item = inst->GetUnscaledItem();
|
||||
|
||||
serialization = StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem;
|
||||
ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For leading quotes (and protection) if a subitem;
|
||||
|
||||
// Instance data
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|",
|
||||
(inst->IsStackable() ? inst->GetCharges() : 0), // stack count
|
||||
0, // unknown
|
||||
(!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot()), // inst slot/merchant slot
|
||||
inst->GetPrice(), // merchant price
|
||||
(!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount()), // inst count/merchant count
|
||||
(inst->IsScaling() ? (inst->GetExp() / 100) : 0), // inst experience
|
||||
(!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot()), // merchant serial number
|
||||
inst->GetRecastTimestamp(), // recast timestamp
|
||||
((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges())), // charge count
|
||||
(inst->IsAttuned() ? 1 : 0), // inst attuned
|
||||
0 // unknown
|
||||
)
|
||||
);
|
||||
|
||||
serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data
|
||||
ss << itoa((inst->IsStackable() ? inst->GetCharges() : 0)); // stack count
|
||||
ss << '|' << itoa(0); // unknown
|
||||
ss << '|' << itoa((!inst->GetMerchantSlot() ? slot_id_in : inst->GetMerchantSlot())); // inst slot/merchant slot
|
||||
ss << '|' << itoa(inst->GetPrice()); // merchant price
|
||||
ss << '|' << itoa((!inst->GetMerchantSlot() ? 1 : inst->GetMerchantCount())); // inst count/merchant count
|
||||
ss << '|' << itoa((inst->IsScaling() ? (inst->GetExp() / 100) : 0)); // inst experience
|
||||
ss << '|' << itoa((!inst->GetMerchantSlot() ? inst->GetSerialNumber() : inst->GetMerchantSlot())); // merchant serial number
|
||||
ss << '|' << itoa(inst->GetRecastTimestamp()); // recast timestamp
|
||||
ss << '|' << itoa(((inst->IsStackable() ? ((inst->GetItem()->ItemType == ItemTypePotion) ? 1 : 0) : inst->GetCharges()))); // charge count
|
||||
ss << '|' << itoa((inst->IsAttuned() ? 1 : 0)); // inst attuned
|
||||
ss << '|' << itoa(0); // unknown
|
||||
ss << '|';
|
||||
|
||||
serialization.append(StringFormat("%i", item->ItemClass)); // item->ItemClass so we can do |%s instead of %s|
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%s|%s|%s|%i|%i|%i|%i|%i|%i|%i|%i|%s|%s|%i|%i",
|
||||
item->Name,
|
||||
item->Lore,
|
||||
item->IDFile,
|
||||
item->ID,
|
||||
((item->Weight > 255) ? 255 : item->Weight),
|
||||
item->NoRent,
|
||||
item->NoDrop,
|
||||
item->Size,
|
||||
item->Slots,
|
||||
item->Price,
|
||||
item->Icon,
|
||||
"0", // unknown
|
||||
"0", // unknown
|
||||
item->BenefitFlag,
|
||||
item->Tradeskills
|
||||
)
|
||||
);
|
||||
ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i",
|
||||
item->CR,
|
||||
item->DR,
|
||||
item->PR,
|
||||
item->MR,
|
||||
item->FR,
|
||||
item->AStr,
|
||||
item->ASta,
|
||||
item->AAgi,
|
||||
item->ADex,
|
||||
item->ACha,
|
||||
item->AInt,
|
||||
item->AWis,
|
||||
item->HP,
|
||||
item->Mana,
|
||||
item->AC
|
||||
)
|
||||
);
|
||||
// Item data
|
||||
ss << itoa(item->ItemClass);
|
||||
ss << '|' << item->Name;
|
||||
ss << '|' << item->Lore;
|
||||
ss << '|' << item->IDFile;
|
||||
ss << '|' << itoa(item->ID);
|
||||
ss << '|' << itoa(((item->Weight > 255) ? 255 : item->Weight));
|
||||
|
||||
ss << '|' << itoa(item->NoRent);
|
||||
ss << '|' << itoa(item->NoDrop);
|
||||
ss << '|' << itoa(item->Size);
|
||||
ss << '|' << itoa(item->Slots);
|
||||
ss << '|' << itoa(item->Price);
|
||||
ss << '|' << itoa(item->Icon);
|
||||
ss << '|' << "0";
|
||||
ss << '|' << "0";
|
||||
ss << '|' << itoa(item->BenefitFlag);
|
||||
ss << '|' << itoa(item->Tradeskills);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i",
|
||||
item->Deity,
|
||||
item->SkillModValue,
|
||||
item->SkillModMax,
|
||||
item->SkillModType,
|
||||
item->BaneDmgRace,
|
||||
item->BaneDmgAmt,
|
||||
item->BaneDmgBody,
|
||||
item->Magic,
|
||||
item->CastTime_,
|
||||
item->ReqLevel,
|
||||
item->BardType,
|
||||
item->BardValue,
|
||||
item->Light,
|
||||
item->Delay
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->CR);
|
||||
ss << '|' << itoa(item->DR);
|
||||
ss << '|' << itoa(item->PR);
|
||||
ss << '|' << itoa(item->MR);
|
||||
ss << '|' << itoa(item->FR);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i",
|
||||
item->RecLevel,
|
||||
item->RecSkill,
|
||||
item->ElemDmgType,
|
||||
item->ElemDmgAmt,
|
||||
item->Range,
|
||||
item->Damage,
|
||||
item->Color,
|
||||
item->Classes,
|
||||
item->Races,
|
||||
"0", // unknown
|
||||
item->MaxCharges,
|
||||
item->ItemType,
|
||||
item->Material,
|
||||
item->SellRate
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->AStr);
|
||||
ss << '|' << itoa(item->ASta);
|
||||
ss << '|' << itoa(item->AAgi);
|
||||
ss << '|' << itoa(item->ADex);
|
||||
ss << '|' << itoa(item->ACha);
|
||||
ss << '|' << itoa(item->AInt);
|
||||
ss << '|' << itoa(item->AWis);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%s|%i|%s|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i",
|
||||
"0", // unknown
|
||||
item->CastTime_,
|
||||
"0", // unknown
|
||||
item->ProcRate,
|
||||
item->CombatEffects,
|
||||
item->Shielding,
|
||||
item->StunResist,
|
||||
item->StrikeThrough,
|
||||
item->ExtraDmgSkill,
|
||||
item->ExtraDmgAmt,
|
||||
item->SpellShield,
|
||||
item->Avoidance,
|
||||
item->Accuracy,
|
||||
item->CharmFileID
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->HP);
|
||||
ss << '|' << itoa(item->Mana);
|
||||
ss << '|' << itoa(item->AC);
|
||||
ss << '|' << itoa(item->Deity);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%s",
|
||||
item->FactionMod1,
|
||||
item->FactionMod2,
|
||||
item->FactionMod3,
|
||||
item->FactionMod4,
|
||||
item->FactionAmt1,
|
||||
item->FactionAmt2,
|
||||
item->FactionAmt3,
|
||||
item->FactionAmt4,
|
||||
item->CharmFile
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->SkillModValue);
|
||||
ss << '|' << itoa(item->SkillModMax);
|
||||
ss << '|' << itoa(item->SkillModType);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i",
|
||||
item->AugType,
|
||||
item->AugSlotType[0],
|
||||
item->AugSlotVisible[0],
|
||||
item->AugSlotType[1],
|
||||
item->AugSlotVisible[1],
|
||||
item->AugSlotType[2],
|
||||
item->AugSlotVisible[2],
|
||||
item->AugSlotType[3],
|
||||
item->AugSlotVisible[3],
|
||||
item->AugSlotType[4],
|
||||
item->AugSlotVisible[4]
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->BaneDmgRace);
|
||||
ss << '|' << itoa(item->BaneDmgAmt);
|
||||
ss << '|' << itoa(item->BaneDmgBody);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%s|%i|%i|%i|%i|%i|%i",
|
||||
item->LDoNTheme,
|
||||
item->LDoNPrice,
|
||||
item->LDoNSold,
|
||||
item->BagType,
|
||||
item->BagSlots,
|
||||
item->BagSize,
|
||||
item->BagWR,
|
||||
item->Book,
|
||||
item->BookType,
|
||||
item->Filename,
|
||||
item->BaneDmgRaceAmt,
|
||||
item->AugRestrict,
|
||||
item->LoreGroup,
|
||||
item->PendingLoreFlag,
|
||||
item->ArtifactFlag,
|
||||
item->SummonedFlag
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->Magic);
|
||||
ss << '|' << itoa(item->CastTime_);
|
||||
ss << '|' << itoa(item->ReqLevel);
|
||||
ss << '|' << itoa(item->BardType);
|
||||
ss << '|' << itoa(item->BardValue);
|
||||
ss << '|' << itoa(item->Light);
|
||||
ss << '|' << itoa(item->Delay);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i|%i",
|
||||
item->Favor,
|
||||
item->FVNoDrop,
|
||||
item->Endur,
|
||||
item->DotShielding,
|
||||
item->Attack,
|
||||
item->Regen,
|
||||
item->ManaRegen,
|
||||
item->EnduranceRegen,
|
||||
item->Haste,
|
||||
item->DamageShield,
|
||||
item->RecastDelay,
|
||||
item->RecastType,
|
||||
item->GuildFavor,
|
||||
item->AugDistiller
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->RecLevel);
|
||||
ss << '|' << itoa(item->RecSkill);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%s|%s|%i|%i|%s|%i|%i|%i|%i|%i|%i",
|
||||
"0", // unknown
|
||||
"0", // unknown
|
||||
item->Attuneable,
|
||||
item->NoPet,
|
||||
"0", // unknown
|
||||
item->PointType,
|
||||
item->PotionBelt,
|
||||
item->PotionBeltSlots,
|
||||
item->StackSize,
|
||||
item->NoTransfer,
|
||||
item->Stackable
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->ElemDmgType);
|
||||
ss << '|' << itoa(item->ElemDmgAmt);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%s",
|
||||
item->Click.Effect,
|
||||
item->Click.Type,
|
||||
item->Click.Level2,
|
||||
item->Click.Level,
|
||||
"0" // Click name
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->Range);
|
||||
ss << '|' << itoa(item->Damage);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%s",
|
||||
item->Proc.Effect,
|
||||
item->Proc.Type,
|
||||
item->Proc.Level2,
|
||||
item->Proc.Level,
|
||||
"0" // Proc name
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->Color);
|
||||
ss << '|' << itoa(item->Classes);
|
||||
ss << '|' << itoa(item->Races);
|
||||
ss << '|' << "0";
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%s",
|
||||
item->Worn.Effect,
|
||||
item->Worn.Type,
|
||||
item->Worn.Level2,
|
||||
item->Worn.Level,
|
||||
"0" // Worn name
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->MaxCharges);
|
||||
ss << '|' << itoa(item->ItemType);
|
||||
ss << '|' << itoa(item->Material);
|
||||
ss << '|' << StringFormat("%f", item->SellRate);
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%s",
|
||||
item->Focus.Effect,
|
||||
item->Focus.Type,
|
||||
item->Focus.Level2,
|
||||
item->Focus.Level,
|
||||
"0" // Focus name
|
||||
)
|
||||
);
|
||||
ss << '|' << "0";
|
||||
ss << '|' << itoa(item->CastTime_);
|
||||
ss << '|' << "0";
|
||||
|
||||
serialization.append(
|
||||
StringFormat(
|
||||
"|%i|%i|%i|%i|%s",
|
||||
item->Scroll.Effect,
|
||||
item->Scroll.Type,
|
||||
item->Scroll.Level2,
|
||||
item->Scroll.Level,
|
||||
"0" // Scroll name
|
||||
)
|
||||
);
|
||||
ss << '|' << itoa(item->ProcRate);
|
||||
ss << '|' << itoa(item->CombatEffects);
|
||||
ss << '|' << itoa(item->Shielding);
|
||||
ss << '|' << itoa(item->StunResist);
|
||||
ss << '|' << itoa(item->StrikeThrough);
|
||||
ss << '|' << itoa(item->ExtraDmgSkill);
|
||||
ss << '|' << itoa(item->ExtraDmgAmt);
|
||||
ss << '|' << itoa(item->SpellShield);
|
||||
ss << '|' << itoa(item->Avoidance);
|
||||
ss << '|' << itoa(item->Accuracy);
|
||||
|
||||
serialization.append(StringFormat("%.*s\"", depth, protection)); // Quotes (and protection, if needed) around static data
|
||||
ss << '|' << itoa(item->CharmFileID);
|
||||
|
||||
ss << '|' << itoa(item->FactionMod1);
|
||||
ss << '|' << itoa(item->FactionMod2);
|
||||
ss << '|' << itoa(item->FactionMod3);
|
||||
ss << '|' << itoa(item->FactionMod4);
|
||||
|
||||
ss << '|' << itoa(item->FactionAmt1);
|
||||
ss << '|' << itoa(item->FactionAmt2);
|
||||
ss << '|' << itoa(item->FactionAmt3);
|
||||
ss << '|' << itoa(item->FactionAmt4);
|
||||
|
||||
ss << '|' << item->CharmFile;
|
||||
|
||||
ss << '|' << itoa(item->AugType);
|
||||
|
||||
ss << '|' << itoa(item->AugSlotType[0]);
|
||||
ss << '|' << itoa(item->AugSlotVisible[0]);
|
||||
ss << '|' << itoa(item->AugSlotType[1]);
|
||||
ss << '|' << itoa(item->AugSlotVisible[1]);
|
||||
ss << '|' << itoa(item->AugSlotType[2]);
|
||||
ss << '|' << itoa(item->AugSlotVisible[2]);
|
||||
ss << '|' << itoa(item->AugSlotType[3]);
|
||||
ss << '|' << itoa(item->AugSlotVisible[3]);
|
||||
ss << '|' << itoa(item->AugSlotType[4]);
|
||||
ss << '|' << itoa(item->AugSlotVisible[4]);
|
||||
|
||||
ss << '|' << itoa(item->LDoNTheme);
|
||||
ss << '|' << itoa(item->LDoNPrice);
|
||||
ss << '|' << itoa(item->LDoNSold);
|
||||
|
||||
ss << '|' << itoa(item->BagType);
|
||||
ss << '|' << itoa(item->BagSlots);
|
||||
ss << '|' << itoa(item->BagSize);
|
||||
ss << '|' << itoa(item->BagWR);
|
||||
|
||||
ss << '|' << itoa(item->Book);
|
||||
ss << '|' << itoa(item->BookType);
|
||||
|
||||
ss << '|' << item->Filename;
|
||||
|
||||
ss << '|' << itoa(item->BaneDmgRaceAmt);
|
||||
ss << '|' << itoa(item->AugRestrict);
|
||||
ss << '|' << itoa(item->LoreGroup);
|
||||
ss << '|' << itoa(item->PendingLoreFlag);
|
||||
ss << '|' << itoa(item->ArtifactFlag);
|
||||
ss << '|' << itoa(item->SummonedFlag);
|
||||
|
||||
ss << '|' << itoa(item->Favor);
|
||||
ss << '|' << itoa(item->FVNoDrop);
|
||||
ss << '|' << itoa(item->Endur);
|
||||
ss << '|' << itoa(item->DotShielding);
|
||||
ss << '|' << itoa(item->Attack);
|
||||
ss << '|' << itoa(item->Regen);
|
||||
ss << '|' << itoa(item->ManaRegen);
|
||||
ss << '|' << itoa(item->EnduranceRegen);
|
||||
ss << '|' << itoa(item->Haste);
|
||||
ss << '|' << itoa(item->DamageShield);
|
||||
ss << '|' << itoa(item->RecastDelay);
|
||||
ss << '|' << itoa(item->RecastType);
|
||||
ss << '|' << itoa(item->GuildFavor);
|
||||
|
||||
ss << '|' << itoa(item->AugDistiller);
|
||||
|
||||
ss << '|' << "0"; // unknown
|
||||
ss << '|' << "0"; // unknown
|
||||
ss << '|' << itoa(item->Attuneable);
|
||||
ss << '|' << itoa(item->NoPet);
|
||||
ss << '|' << "0"; // unknown
|
||||
ss << '|' << itoa(item->PointType);
|
||||
|
||||
ss << '|' << itoa(item->PotionBelt);
|
||||
ss << '|' << itoa(item->PotionBeltSlots);
|
||||
ss << '|' << itoa(item->StackSize);
|
||||
ss << '|' << itoa(item->NoTransfer);
|
||||
ss << '|' << itoa(item->Stackable);
|
||||
|
||||
ss << '|' << itoa(item->Click.Effect);
|
||||
ss << '|' << itoa(item->Click.Type);
|
||||
ss << '|' << itoa(item->Click.Level2);
|
||||
ss << '|' << itoa(item->Click.Level);
|
||||
ss << '|' << "0"; // Click name
|
||||
|
||||
ss << '|' << itoa(item->Proc.Effect);
|
||||
ss << '|' << itoa(item->Proc.Type);
|
||||
ss << '|' << itoa(item->Proc.Level2);
|
||||
ss << '|' << itoa(item->Proc.Level);
|
||||
ss << '|' << "0"; // Proc name
|
||||
|
||||
ss << '|' << itoa(item->Worn.Effect);
|
||||
ss << '|' << itoa(item->Worn.Type);
|
||||
ss << '|' << itoa(item->Worn.Level2);
|
||||
ss << '|' << itoa(item->Worn.Level);
|
||||
ss << '|' << "0"; // Worn name
|
||||
|
||||
ss << '|' << itoa(item->Focus.Effect);
|
||||
ss << '|' << itoa(item->Focus.Type);
|
||||
ss << '|' << itoa(item->Focus.Level2);
|
||||
ss << '|' << itoa(item->Focus.Level);
|
||||
ss << '|' << "0"; // Focus name
|
||||
|
||||
ss << '|' << itoa(item->Scroll.Effect);
|
||||
ss << '|' << itoa(item->Scroll.Type);
|
||||
ss << '|' << itoa(item->Scroll.Level2);
|
||||
ss << '|' << itoa(item->Scroll.Level);
|
||||
ss << '|' << "0"; // Scroll name
|
||||
|
||||
ss << StringFormat("%.*s\"", depth, protection); // Quotes (and protection, if needed) around static data
|
||||
|
||||
// Sub data
|
||||
for (int index = SUB_INDEX_BEGIN; index < consts::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst *sub = inst->GetItem(index);
|
||||
if (!sub) {
|
||||
serialization.push_back('|'); // Sub items (empty)
|
||||
}
|
||||
else {
|
||||
std::string sub_item = SerializeItem(sub, 0, (depth + 1));
|
||||
serialization.append(StringFormat("|%s", sub_item.c_str())); // Sub items
|
||||
}
|
||||
ss << '|';
|
||||
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
SerializeItem(ss, sub, 0, (depth + 1));
|
||||
}
|
||||
|
||||
serialization.append(StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : ""))); // For trailing quotes (and protection) if a subitem;
|
||||
ss << StringFormat("%.*s%s", (depth ? (depth - 1) : 0), protection, (depth ? "\"" : "")); // For trailing quotes (and protection) if a subitem;
|
||||
|
||||
return serialization;
|
||||
if (!depth)
|
||||
ss.write("\0", 1);
|
||||
}
|
||||
|
||||
static inline int16 ServerToTitaniumSlot(uint32 serverSlot)
|
||||
|
||||
@ -22,7 +22,7 @@ namespace UF
|
||||
static OpcodeManager *opcodes = nullptr;
|
||||
static Strategy struct_strategy;
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id, uint32 *length, uint8 depth);
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id, uint8 depth);
|
||||
|
||||
// server to client inventory location converters
|
||||
static inline uint32 ServerToUFSlot(uint32 serverSlot);
|
||||
@ -473,27 +473,23 @@ namespace UF
|
||||
ENCODE(OP_CharInventory)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
if (in->size == 0) {
|
||||
|
||||
if (!in->size) {
|
||||
in->size = 4;
|
||||
in->pBuffer = new uchar[in->size];
|
||||
*((uint32 *)in->pBuffer) = 0;
|
||||
memset(in->pBuffer, 0, in->size);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
return;
|
||||
}
|
||||
|
||||
//store away the emu struct
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
|
||||
int ItemCount = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
|
||||
if (ItemCount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
|
||||
int item_count = in->size / sizeof(InternalSerializedItem_Struct);
|
||||
if (!item_count || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Wrong size on outbound %s: Got %d, expected multiple of %d",
|
||||
opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
|
||||
|
||||
@ -501,39 +497,28 @@ namespace UF
|
||||
return;
|
||||
}
|
||||
|
||||
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *)in->pBuffer;
|
||||
InternalSerializedItem_Struct* eq = (InternalSerializedItem_Struct*)in->pBuffer;
|
||||
|
||||
in->pBuffer = new uchar[4];
|
||||
*(uint32 *)in->pBuffer = ItemCount;
|
||||
in->size = 4;
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
for (int r = 0; r < ItemCount; r++, eq++) {
|
||||
ss.write((const char*)&item_count, sizeof(uint32));
|
||||
|
||||
uint32 Length = 0;
|
||||
char* Serialized = SerializeItem((const ItemInst*)eq->inst, eq->slot_id, &Length, 0);
|
||||
for (int index = 0; index < item_count; ++index, ++eq) {
|
||||
SerializeItem(ss, (const ItemInst*)eq->inst, eq->slot_id, 0);
|
||||
if (ss.tellp() == last_pos)
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
|
||||
if (Serialized) {
|
||||
|
||||
uchar *OldBuffer = in->pBuffer;
|
||||
in->pBuffer = new uchar[in->size + Length];
|
||||
memcpy(in->pBuffer, OldBuffer, in->size);
|
||||
|
||||
safe_delete_array(OldBuffer);
|
||||
|
||||
memcpy(in->pBuffer + in->size, Serialized, Length);
|
||||
in->size += Length;
|
||||
|
||||
safe_delete_array(Serialized);
|
||||
}
|
||||
else {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[ERROR] Serialization failed on item slot %d during OP_CharInventory. Item skipped.", eq->slot_id);
|
||||
}
|
||||
last_pos = ss.tellp();
|
||||
}
|
||||
|
||||
delete[] __emu_buffer;
|
||||
std::string serialized = ss.str();
|
||||
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Sending inventory to client");
|
||||
//Log.Hex(Logs::Netcode, in->pBuffer, in->size);
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
@ -1259,29 +1244,37 @@ namespace UF
|
||||
ENCODE(OP_ItemPacket)
|
||||
{
|
||||
//consume the packet
|
||||
EQApplicationPacket *in = *p;
|
||||
EQApplicationPacket* in = *p;
|
||||
*p = nullptr;
|
||||
|
||||
unsigned char *__emu_buffer = in->pBuffer;
|
||||
ItemPacket_Struct *old_item_pkt = (ItemPacket_Struct *)__emu_buffer;
|
||||
InternalSerializedItem_Struct *int_struct = (InternalSerializedItem_Struct *)(old_item_pkt->SerializedItem);
|
||||
//store away the emu struct
|
||||
uchar* __emu_buffer = in->pBuffer;
|
||||
//ItemPacket_Struct* old_item_pkt = (ItemPacket_Struct*)__emu_buffer;
|
||||
//InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(old_item_pkt->SerializedItem);
|
||||
InternalSerializedItem_Struct* int_struct = (InternalSerializedItem_Struct*)(&__emu_buffer[4]);
|
||||
|
||||
uint32 length;
|
||||
char *serialized = SerializeItem((ItemInst *)int_struct->inst, int_struct->slot_id, &length, 0);
|
||||
std::stringstream ss(std::stringstream::in | std::stringstream::out);
|
||||
std::stringstream::pos_type last_pos = ss.tellp();
|
||||
|
||||
if (!serialized) {
|
||||
ss.write((const char*)__emu_buffer, 4);
|
||||
|
||||
SerializeItem(ss, (const ItemInst*)int_struct->inst, int_struct->slot_id, 0);
|
||||
if (ss.tellp() == last_pos) {
|
||||
Log.Out(Logs::General, Logs::Netcode, "[STRUCTS] Serialization failed on item slot %d.", int_struct->slot_id);
|
||||
delete in;
|
||||
return;
|
||||
}
|
||||
in->size = length + 4;
|
||||
in->pBuffer = new unsigned char[in->size];
|
||||
ItemPacket_Struct *new_item_pkt = (ItemPacket_Struct *)in->pBuffer;
|
||||
new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(new_item_pkt->SerializedItem, serialized, length);
|
||||
|
||||
std::string serialized = ss.str();
|
||||
|
||||
in->size = serialized.size();
|
||||
in->pBuffer = new uchar[in->size];
|
||||
//ItemPacket_Struct* new_item_pkt = (ItemPacket_Struct*)in->pBuffer;
|
||||
//new_item_pkt->PacketType = old_item_pkt->PacketType;
|
||||
memcpy(in->pBuffer, serialized.c_str(), serialized.size());
|
||||
|
||||
delete[] __emu_buffer;
|
||||
safe_delete_array(serialized);
|
||||
|
||||
dest->FastQueuePacket(&in, ack_req);
|
||||
}
|
||||
|
||||
@ -3822,43 +3815,36 @@ namespace UF
|
||||
return NextItemInstSerialNumber;
|
||||
}
|
||||
|
||||
char* SerializeItem(const ItemInst *inst, int16 slot_id_in, uint32 *length, uint8 depth)
|
||||
void SerializeItem(std::stringstream& ss, const ItemInst *inst, int16 slot_id_in, uint8 depth)
|
||||
{
|
||||
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 Item_Struct *item = inst->GetUnscaledItem();
|
||||
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Serialize called for: %s", item->Name);
|
||||
|
||||
UF::structs::ItemSerializationHeader hdr;
|
||||
hdr.stacksize = stackable ? charges : 1;
|
||||
|
||||
hdr.stacksize = (inst->IsStackable() ? ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()) : 1);
|
||||
hdr.unknown004 = 0;
|
||||
|
||||
int32 slot_id = ServerToUFSlot(slot_id_in);
|
||||
|
||||
hdr.slot = (merchant_slot == 0) ? slot_id : merchant_slot;
|
||||
hdr.slot = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : slot_id);
|
||||
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.merchant_slot = (inst->GetMerchantSlot() ? inst->GetMerchantCount() : 1);
|
||||
hdr.scaled_value = (inst->IsScaling() ? (inst->GetExp() / 100) : 0);
|
||||
hdr.instance_id = (inst->GetMerchantSlot() ? inst->GetMerchantSlot() : inst->GetSerialNumber());
|
||||
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.charges = (inst->IsStackable() ? (item->MaxCharges ? 1 : 0) : ((inst->GetCharges() > 254) ? 0xFFFFFFFF : inst->GetCharges()));
|
||||
hdr.inst_nodrop = (inst->IsAttuned() ? 1 : 0);
|
||||
hdr.unknown044 = 0;
|
||||
hdr.unknown048 = 0;
|
||||
hdr.unknown052 = 0;
|
||||
hdr.isEvolving = item->EvolvingItem;
|
||||
|
||||
ss.write((const char*)&hdr, sizeof(UF::structs::ItemSerializationHeader));
|
||||
|
||||
if (item->EvolvingItem > 0) {
|
||||
UF::structs::EvolvingItem evotop;
|
||||
|
||||
evotop.unknown001 = 0;
|
||||
evotop.unknown002 = 0;
|
||||
evotop.unknown003 = 0;
|
||||
@ -3867,70 +3853,55 @@ namespace UF
|
||||
evotop.progress = 0;
|
||||
evotop.Activated = 1;
|
||||
evotop.evomaxlevel = item->EvolvingMax;
|
||||
|
||||
ss.write((const char*)&evotop, sizeof(UF::structs::EvolvingItem));
|
||||
}
|
||||
|
||||
//ORNAMENT IDFILE / ICON -
|
||||
int ornamentationAugtype = RuleI(Character, OrnamentationAugmentType);
|
||||
uint16 ornaIcon = 0;
|
||||
if (inst->GetOrnamentationAug(ornamentationAugtype)) {
|
||||
const Item_Struct *aug_weap = inst->GetOrnamentationAug(ornamentationAugtype)->GetItem();
|
||||
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ornaIcon = aug_weap->Icon;
|
||||
|
||||
ss.write(aug_weap->IDFile, strlen(aug_weap->IDFile));
|
||||
}
|
||||
else if (inst->GetOrnamentationIDFile() && inst->GetOrnamentationIcon()) {
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
ss.write(tmp, strlen(tmp));
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ornaIcon = inst->GetOrnamentationIcon();
|
||||
char tmp[30]; memset(tmp, 0x0, 30); sprintf(tmp, "IT%d", inst->GetOrnamentationIDFile());
|
||||
|
||||
ss.write(tmp, strlen(tmp));
|
||||
}
|
||||
else {
|
||||
ss.write((const char*)&null_term, sizeof(uint8)); //no idfile
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
UF::structs::ItemSerializationHeaderFinish hdrf;
|
||||
|
||||
hdrf.ornamentIcon = ornaIcon;
|
||||
hdrf.unknown060 = 0; //This is Always 0.. or it breaks shit..
|
||||
hdrf.unknown061 = 0; //possibly ornament / special ornament
|
||||
hdrf.isCopied = 0; //Flag for item to be 'Copied'
|
||||
hdrf.ItemClass = item->ItemClass;
|
||||
|
||||
ss.write((const char*)&hdrf, sizeof(UF::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
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("\0", 1);
|
||||
|
||||
UF::structs::ItemBodyStruct ibs;
|
||||
memset(&ibs, 0, sizeof(UF::structs::ItemBodyStruct));
|
||||
|
||||
ibs.id = item->ID;
|
||||
// weight is uint8 in the struct, and some weights exceed that, so capping at 255.
|
||||
ibs.weight = (item->Weight > 255) ? 255 : item->Weight;
|
||||
ibs.weight = ((item->Weight > 255) ? 255 : item->Weight);
|
||||
ibs.norent = item->NoRent;
|
||||
ibs.nodrop = item->NoDrop;
|
||||
ibs.attune = item->Attuneable;
|
||||
@ -4016,14 +3987,8 @@ namespace UF
|
||||
|
||||
//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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
UF::structs::ItemSecondaryBodyStruct isbs;
|
||||
memset(&isbs, 0, sizeof(UF::structs::ItemSecondaryBodyStruct));
|
||||
@ -4031,11 +3996,10 @@ namespace UF
|
||||
isbs.augtype = item->AugType;
|
||||
isbs.augrestrict = item->AugRestrict;
|
||||
|
||||
for (int x = 0; 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];
|
||||
for (int index = 0; index < consts::ITEM_COMMON_SIZE; ++index) {
|
||||
isbs.augslots[index].type = item->AugSlotType[index];
|
||||
isbs.augslots[index].visible = item->AugSlotVisible[index];
|
||||
isbs.augslots[index].unknown = item->AugSlotUnk2[index];
|
||||
}
|
||||
|
||||
isbs.ldonpoint_type = item->PointType;
|
||||
@ -4055,14 +4019,8 @@ namespace UF
|
||||
ss.write((const char*)&isbs, sizeof(UF::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));
|
||||
}
|
||||
ss.write("\0", 1);
|
||||
|
||||
UF::structs::ItemTertiaryBodyStruct itbs;
|
||||
memset(&itbs, 0, sizeof(UF::structs::ItemTertiaryBodyStruct));
|
||||
@ -4082,7 +4040,7 @@ namespace UF
|
||||
|
||||
itbs.potion_belt_enabled = item->PotionBelt;
|
||||
itbs.potion_belt_slots = item->PotionBeltSlots;
|
||||
itbs.stacksize = stackable ? item->StackSize : 0;
|
||||
itbs.stacksize = (inst->IsStackable() ? item->StackSize : 0);
|
||||
itbs.no_transfer = item->NoTransfer;
|
||||
itbs.expendablearrow = item->ExpendableArrow;
|
||||
|
||||
@ -4106,14 +4064,8 @@ namespace UF
|
||||
ss.write((const char*)&ices, sizeof(UF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // clickunk7
|
||||
|
||||
@ -4129,14 +4081,8 @@ namespace UF
|
||||
ss.write((const char*)&ipes, sizeof(UF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown5
|
||||
|
||||
@ -4151,14 +4097,8 @@ namespace UF
|
||||
ss.write((const char*)&iwes, sizeof(UF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -4173,14 +4113,8 @@ namespace UF
|
||||
ss.write((const char*)&ifes, sizeof(UF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -4195,14 +4129,8 @@ namespace UF
|
||||
ss.write((const char*)&ises, sizeof(UF::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("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
|
||||
@ -4225,7 +4153,7 @@ namespace UF
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
}
|
||||
else */
|
||||
ss.write((const char*)&null_term, sizeof(uint8));
|
||||
ss.write("\0", 1);
|
||||
|
||||
ss.write((const char*)&effect_unknown, sizeof(int32)); // unknown6
|
||||
// End of Effects
|
||||
@ -4255,67 +4183,44 @@ namespace UF
|
||||
iqbs.HeroicSVCorrup = item->HeroicSVCorrup;
|
||||
iqbs.HealAmt = item->HealAmt;
|
||||
iqbs.SpellDmg = item->SpellDmg;
|
||||
iqbs.clairvoyance = item->Clairvoyance;
|
||||
|
||||
iqbs.subitem_count = 0;
|
||||
|
||||
char *SubSerializations[10]; // <watch>
|
||||
|
||||
uint32 SubLengths[10];
|
||||
|
||||
for (int x = SUB_INDEX_BEGIN; x < EQEmu::legacy::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 >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END) // (< 30) - no cursor?
|
||||
//SubSlotNumber = (((slot_id_in + 3) * 10) + x + 1);
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + x + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2000) * 10) + 2030 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + x);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
//SubSlotNumber = (((slot_id_in - 2500) * 10) + 2530 + x + 1);
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + x);
|
||||
else
|
||||
SubSlotNumber = slot_id_in; // ???????
|
||||
|
||||
/*
|
||||
// TEST CODE: <watch>
|
||||
SubSlotNumber = Inventory::CalcSlotID(slot_id_in, x);
|
||||
*/
|
||||
|
||||
SubSerializations[x] = SerializeItem(subitem, SubSlotNumber, &SubLengths[x], depth + 1);
|
||||
}
|
||||
}
|
||||
|
||||
iqbs.Clairvoyance = item->Clairvoyance;
|
||||
|
||||
ss.write((const char*)&iqbs, sizeof(UF::structs::ItemQuaternaryBodyStruct));
|
||||
|
||||
for (int x = 0; x < 10; ++x) {
|
||||
std::stringstream::pos_type count_pos = ss.tellp();
|
||||
uint32 subitem_count = 0;
|
||||
|
||||
if (SubSerializations[x]) {
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.write((const char*)&x, sizeof(uint32));
|
||||
for (uint32 index = SUB_INDEX_BEGIN; index < EQEmu::legacy::ITEM_CONTAINER_SIZE; ++index) {
|
||||
ItemInst* sub = inst->GetItem(index);
|
||||
if (!sub)
|
||||
continue;
|
||||
|
||||
ss.write(SubSerializations[x], SubLengths[x]);
|
||||
int SubSlotNumber = INVALID_INDEX;
|
||||
if (slot_id_in >= EQEmu::legacy::GENERAL_BEGIN && slot_id_in <= EQEmu::legacy::GENERAL_END)
|
||||
SubSlotNumber = (((slot_id_in + 3) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + index + 1);
|
||||
else if (slot_id_in >= EQEmu::legacy::BANK_BEGIN && slot_id_in <= EQEmu::legacy::BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::BANK_BAGS_BEGIN + index);
|
||||
else if (slot_id_in >= EQEmu::legacy::SHARED_BANK_BEGIN && slot_id_in <= EQEmu::legacy::SHARED_BANK_END)
|
||||
SubSlotNumber = (((slot_id_in - EQEmu::legacy::SHARED_BANK_BEGIN) * EQEmu::legacy::ITEM_CONTAINER_SIZE) + EQEmu::legacy::SHARED_BANK_BAGS_BEGIN + index);
|
||||
else
|
||||
SubSlotNumber = slot_id_in;
|
||||
|
||||
safe_delete_array(SubSerializations[x]);
|
||||
}
|
||||
ss.write((const char*)&index, sizeof(uint32));
|
||||
|
||||
SerializeItem(ss, sub, SubSlotNumber, (depth + 1));
|
||||
++subitem_count;
|
||||
}
|
||||
|
||||
char* item_serial = new char[ss.tellp()];
|
||||
memset(item_serial, 0, ss.tellp());
|
||||
memcpy(item_serial, ss.str().c_str(), ss.tellp());
|
||||
if (subitem_count) {
|
||||
std::stringstream::pos_type cur_pos = ss.tellp();
|
||||
ss.seekp(count_pos);
|
||||
|
||||
*length = ss.tellp();
|
||||
return item_serial;
|
||||
ss.write((const char*)&subitem_count, sizeof(uint32));
|
||||
|
||||
ss.seekp(cur_pos);
|
||||
}
|
||||
}
|
||||
|
||||
static inline uint32 ServerToUFSlot(uint32 serverSlot)
|
||||
|
||||
@ -4281,14 +4281,13 @@ struct ItemQuaternaryBodyStruct
|
||||
int32 HeroicSVCorrup;
|
||||
int32 HealAmt;
|
||||
int32 SpellDmg;
|
||||
int32 clairvoyance;
|
||||
int32 Clairvoyance;
|
||||
uint8 unknown18; //Power Source Capacity or evolve filename?
|
||||
uint32 evolve_string; // Some String, but being evolution related is just a guess
|
||||
uint8 unknown19;
|
||||
uint32 unknown20; // Bard Stuff?
|
||||
uint32 unknown21;
|
||||
uint32 unknown22;
|
||||
uint32 subitem_count;
|
||||
};
|
||||
|
||||
struct AugmentInfo_Struct
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user