Reworked client translators' SerializeItem() to recursive, single buffer methodology

This commit is contained in:
Uleat
2016-05-10 20:16:27 -04:00
parent de48d79b27
commit 37b84c4db1
12 changed files with 808 additions and 1379 deletions
+124 -233
View File
@@ -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)