trevius
04-11-2009, 04:39 AM
Since the EQEmu forums have been down frequently lately, I started a discussion on this on the PEQ forums here:
http://www.projecteq.net/phpBB2/viewtopic.php?t=6999
But, while the EQEmu forums are up, this is probably the best place to discuss the SoF Augment work.
With much help from Leere and a few others in that thread, I now have augments actually working on my test server for the most part. The only thing left to do is getting augmented items that are stored within bags to work properly. Unfortunately, I cannot put any of this new code on the SVN until it is fully functional, as it causes client crashes if an item with augments is stored inside of a bag. Once it is fully functional though, I will get it on the SVN ASAP so people can start testing it out.
Basically, the main issue right now is that Items in bag slots are considered sub items, and augments inside an item are also considered sub items. So, augments inside items that are inside a bag would be considered sub items inside sub items. The sub item stuff is working fine, but sub items inside sub items is not.
Here is the basics of how augments are loaded in SoF:
1. If an item has augments in it, the last 4 bytes (int32) in the that items part of the packet will be the total count of augments in the item.
2. The next 4 bytes after that are a spacer between the item and it's augments.
3. That spacer is an int32 that reports the number of the aug slot that the following augment is supposed to go in.
4. This is not the same as the aug slot type, it is a number from 0 to 4 (5 is the max number of aug slots).
5. After that, is sent, the actual augment item serialization for that aug slot is sent.
6. This continues until all of the reported aug slots are accounted for. If everything doesn't go in exactly as it needs to, it will throw off the entire rest of the packet and almost always cause a client crash while attempting to load all of the items.
Right now, all of that is working on my test server, but the sub items within sub items isn't being handled correctly yet, so it breaks the serialization.
OK, onto the actual code I have set for this so far. I am sure that the code I have for this could be adjusted to work better, but for the purpose of getting augments actually working, this seems to work fairly well (other than the sub items issue of course):
NOTE: This code is for TESTING ONLY! Do not try to add this to a production server as it WILL cause crashes. I am only submitting this here so other people can help finish the code for augment handling.
In SoF_structs.h change the following line at the end of the item structure here:
uint8 padding[8]; //some of this is null term for augs + end of item, shouldn't do this this way but for now
To this:
uint32 evolve_string; // Some String, but being evolution related is just a guess
uint32 augment_count;
Then, in SoF.cpp, replace the entire OP_CharInventory encode here:
ENCODE(OP_CharInventory) {
//consume the packet
EQApplicationPacket *in = *p;
*p = NULL;
if(in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if(itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
_log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *) in->pBuffer;
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
//EQApplicationPacket * outapp = new EQApplicationPacket((const EmuOpcode)0x78Cd);
int r;
char* serialized = NULL;
uint32 length = 0;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
EQApplicationPacket * outapp = new EQApplicationPacket(OP_ItemPacket, length+4);
uint32 * type = (uint32*)outapp->pBuffer;
*type = ItemPacketTrade;
memcpy(outapp->pBuffer+4, serialized, length);
_log(NET__ERROR, "Sending item to client");
_hex(NET__ERROR, outapp->pBuffer, outapp->size);
dest->FastQueuePacket(&outapp);
delete[] serialized;
serialized = NULL;
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id <= 30)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
else if((const ItemInst*)eq->inst,eq->slot_id >= 2000 && (const ItemInst*)eq->inst,eq->slot_id <= 2023)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id-2000)*10)+2030+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
else if((const ItemInst*)eq->inst,eq->slot_id >= 2500 && (const ItemInst*)eq->inst,eq->slot_id <= 2501)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id-2500)*10)+2530+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
}
}
//Proper way below crashing
//Workaround above
//Goal: get the item struct good enough that we don't need the workaround.
/*uchar *data = NULL;
uchar *dataptr = NULL;
uchar *tempdata = NULL;
//do the transform...
int r;
data = new uchar[4];
uint32 *item_opcode;
item_opcode = (uint32*)data;
*item_opcode = 0x69;//0x35;
uint32 total_length = 4;
uint32 length = 0;
char* serialized = NULL;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id < 30)
{
for(int x = 0; x < 10; ++x)
{
serialized = NULL;
uint32 sub_length = 0;
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+sub_length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, sub_length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
}
}
}
}
else
{
_log(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id);
}
}
in->size = total_length;
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, data, in->size);
delete[] __emu_buffer;
_log(NET__ERROR, "Sending inventory to client");
_hex(NET__ERROR, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);*/
}
With this:
ENCODE(OP_CharInventory) {
//consume the packet
EQApplicationPacket *in = *p;
*p = NULL;
if(in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if(itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
_log(NET__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;
uchar *data = NULL;
//uchar *dataptr = NULL;
uchar *tempdata = NULL;
data = new uchar[4];
uint32 *item_opcode;
item_opcode = (uint32*)data;
*item_opcode = 500; //should replace this with Total Item Count including Sub Items
//do the transform...
int r;
uint32 total_length = 4;
uint32 length = 0;
char* serialized = NULL;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
bool normal_item = false;
const Item_Struct *item = ((const ItemInst*)eq->inst)->GetItem();
uint8 itemclass = item->ItemClass;
if(itemclass == 0)
normal_item = true;
tempdata = data;
data = NULL;
data = new uchar[total_length+length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
for(int x = 0; x < 10; ++x)
{
serialized = NULL;
uint32 sub_length = 0;
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id < 30)
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
else if((const ItemInst*)eq->inst,eq->slot_id >= 2000 && (const ItemInst*)eq->inst,eq->slot_id <= 2023)
serialized = SerializeItem(subitem, (((eq->slot_id-2000)*10)+2030+x+1), &sub_length, 0);
else if((const ItemInst*)eq->inst,eq->slot_id >= 2500 && (const ItemInst*)eq->inst,eq->slot_id <= 2501)
serialized = SerializeItem(subitem, (((eq->slot_id-2500)*10)+2530+x+1), &sub_length, 0);
else
serialized = SerializeItem(subitem, eq->slot_id, &sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
if(normal_item)
{
data = new uchar[total_length+sub_length+4];
memcpy(data, tempdata, total_length);
*((uint32*)(data+total_length)) = x;
total_length += 4;
memcpy(data+total_length, serialized, sub_length);
total_length += sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
else
{
data = new uchar[total_length+sub_length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, sub_length);
total_length += sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
/*
for(int k = 0; k < MAX_AUGMENT_SLOTS; ++k)
{
serialized = NULL;
uint32 sub_sub_length = 0;
const ItemInst* subsubitem = (((const ItemInst*)eq->inst)eq->inst)->GetItem(k);
if(subsubitem)
{
serialized = SerializeItem(subsubitem, eq->slot_id, &sub_sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+sub_sub_length+4];
memcpy(data, tempdata, total_length);
*((uint32*)(data+total_length)) = k;
total_length += 4;
memcpy(data+total_length, serialized, sub_sub_length);
total_length += sub_sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
}
}
*/
}
}
}
}
}
else
{
_log(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id);
}
}
in->size = total_length;
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, data, in->size);
delete[] __emu_buffer;
_log(NET__ERROR, "Sending inventory to client");
_hex(NET__ERROR, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
Last, after the following line from the Item Serialization in SoF.cpp here:
itbs.unknown15 = 0xffffffff;
Add the following code:
uint8 aug_total = 0;
if(hdr.ItemClass == 0)
{
for(int x = 0; x < 5; ++x)
{
const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x);
if(subitem)
{
aug_total++;
}
}
}
itbs.augment_count = aug_total;
I think that is it. This should let you load a character that has augmented items as long as none of the augmented items are stored inside of a bag.
http://www.projecteq.net/phpBB2/viewtopic.php?t=6999
But, while the EQEmu forums are up, this is probably the best place to discuss the SoF Augment work.
With much help from Leere and a few others in that thread, I now have augments actually working on my test server for the most part. The only thing left to do is getting augmented items that are stored within bags to work properly. Unfortunately, I cannot put any of this new code on the SVN until it is fully functional, as it causes client crashes if an item with augments is stored inside of a bag. Once it is fully functional though, I will get it on the SVN ASAP so people can start testing it out.
Basically, the main issue right now is that Items in bag slots are considered sub items, and augments inside an item are also considered sub items. So, augments inside items that are inside a bag would be considered sub items inside sub items. The sub item stuff is working fine, but sub items inside sub items is not.
Here is the basics of how augments are loaded in SoF:
1. If an item has augments in it, the last 4 bytes (int32) in the that items part of the packet will be the total count of augments in the item.
2. The next 4 bytes after that are a spacer between the item and it's augments.
3. That spacer is an int32 that reports the number of the aug slot that the following augment is supposed to go in.
4. This is not the same as the aug slot type, it is a number from 0 to 4 (5 is the max number of aug slots).
5. After that, is sent, the actual augment item serialization for that aug slot is sent.
6. This continues until all of the reported aug slots are accounted for. If everything doesn't go in exactly as it needs to, it will throw off the entire rest of the packet and almost always cause a client crash while attempting to load all of the items.
Right now, all of that is working on my test server, but the sub items within sub items isn't being handled correctly yet, so it breaks the serialization.
OK, onto the actual code I have set for this so far. I am sure that the code I have for this could be adjusted to work better, but for the purpose of getting augments actually working, this seems to work fairly well (other than the sub items issue of course):
NOTE: This code is for TESTING ONLY! Do not try to add this to a production server as it WILL cause crashes. I am only submitting this here so other people can help finish the code for augment handling.
In SoF_structs.h change the following line at the end of the item structure here:
uint8 padding[8]; //some of this is null term for augs + end of item, shouldn't do this this way but for now
To this:
uint32 evolve_string; // Some String, but being evolution related is just a guess
uint32 augment_count;
Then, in SoF.cpp, replace the entire OP_CharInventory encode here:
ENCODE(OP_CharInventory) {
//consume the packet
EQApplicationPacket *in = *p;
*p = NULL;
if(in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if(itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
_log(NET__STRUCTS, "Wrong size on outbound %s: Got %d, expected multiple of %d", opcodes->EmuToName(in->GetOpcode()), in->size, sizeof(InternalSerializedItem_Struct));
delete in;
return;
}
InternalSerializedItem_Struct *eq = (InternalSerializedItem_Struct *) in->pBuffer;
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
//EQApplicationPacket * outapp = new EQApplicationPacket((const EmuOpcode)0x78Cd);
int r;
char* serialized = NULL;
uint32 length = 0;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
EQApplicationPacket * outapp = new EQApplicationPacket(OP_ItemPacket, length+4);
uint32 * type = (uint32*)outapp->pBuffer;
*type = ItemPacketTrade;
memcpy(outapp->pBuffer+4, serialized, length);
_log(NET__ERROR, "Sending item to client");
_hex(NET__ERROR, outapp->pBuffer, outapp->size);
dest->FastQueuePacket(&outapp);
delete[] serialized;
serialized = NULL;
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id <= 30)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
else if((const ItemInst*)eq->inst,eq->slot_id >= 2000 && (const ItemInst*)eq->inst,eq->slot_id <= 2023)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id-2000)*10)+2030+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
else if((const ItemInst*)eq->inst,eq->slot_id >= 2500 && (const ItemInst*)eq->inst,eq->slot_id <= 2501)
{
for(int x = 0; x < 10; ++x)
{
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
uint32 sub_length;
serialized = NULL;
serialized = SerializeItem(subitem, (((eq->slot_id-2500)*10)+2530+x+1), &sub_length, 0);
if(serialized)
{
EQApplicationPacket * suboutapp = new EQApplicationPacket(OP_ItemPacket, sub_length+4);
uint32 * subtype = (uint32*)suboutapp->pBuffer;
*subtype = ItemPacketTrade;
memcpy(suboutapp->pBuffer+4, serialized, sub_length);
_log(NET__ERROR, "Sending sub item to client");
_hex(NET__ERROR, suboutapp->pBuffer, suboutapp->size);
dest->FastQueuePacket(&suboutapp);
delete[] serialized;
serialized = NULL;
}
}
}
}
}
}
//Proper way below crashing
//Workaround above
//Goal: get the item struct good enough that we don't need the workaround.
/*uchar *data = NULL;
uchar *dataptr = NULL;
uchar *tempdata = NULL;
//do the transform...
int r;
data = new uchar[4];
uint32 *item_opcode;
item_opcode = (uint32*)data;
*item_opcode = 0x69;//0x35;
uint32 total_length = 4;
uint32 length = 0;
char* serialized = NULL;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id < 30)
{
for(int x = 0; x < 10; ++x)
{
serialized = NULL;
uint32 sub_length = 0;
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+sub_length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, sub_length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
}
}
}
}
else
{
_log(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id);
}
}
in->size = total_length;
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, data, in->size);
delete[] __emu_buffer;
_log(NET__ERROR, "Sending inventory to client");
_hex(NET__ERROR, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);*/
}
With this:
ENCODE(OP_CharInventory) {
//consume the packet
EQApplicationPacket *in = *p;
*p = NULL;
if(in->size == 0) {
in->size = 4;
in->pBuffer = new uchar[in->size];
*((uint32 *) in->pBuffer) = 0;
dest->FastQueuePacket(&in, ack_req);
return;
}
//store away the emu struct
unsigned char *__emu_buffer = in->pBuffer;
int itemcount = in->size / sizeof(InternalSerializedItem_Struct);
if(itemcount == 0 || (in->size % sizeof(InternalSerializedItem_Struct)) != 0) {
_log(NET__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;
uchar *data = NULL;
//uchar *dataptr = NULL;
uchar *tempdata = NULL;
data = new uchar[4];
uint32 *item_opcode;
item_opcode = (uint32*)data;
*item_opcode = 500; //should replace this with Total Item Count including Sub Items
//do the transform...
int r;
uint32 total_length = 4;
uint32 length = 0;
char* serialized = NULL;
for(r = 0; r < itemcount; r++, eq++)
{
length = 0;
serialized = NULL;
serialized = SerializeItem((const ItemInst*)eq->inst,eq->slot_id,&length,0);
if(serialized)
{
bool normal_item = false;
const Item_Struct *item = ((const ItemInst*)eq->inst)->GetItem();
uint8 itemclass = item->ItemClass;
if(itemclass == 0)
normal_item = true;
tempdata = data;
data = NULL;
data = new uchar[total_length+length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, length);
total_length += length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
for(int x = 0; x < 10; ++x)
{
serialized = NULL;
uint32 sub_length = 0;
const ItemInst* subitem = ((const ItemInst*)eq->inst)->GetItem(x);
if(subitem)
{
if((const ItemInst*)eq->inst,eq->slot_id >= 22 && (const ItemInst*)eq->inst,eq->slot_id < 30)
serialized = SerializeItem(subitem, (((eq->slot_id+3)*10)+x+1), &sub_length, 0);
else if((const ItemInst*)eq->inst,eq->slot_id >= 2000 && (const ItemInst*)eq->inst,eq->slot_id <= 2023)
serialized = SerializeItem(subitem, (((eq->slot_id-2000)*10)+2030+x+1), &sub_length, 0);
else if((const ItemInst*)eq->inst,eq->slot_id >= 2500 && (const ItemInst*)eq->inst,eq->slot_id <= 2501)
serialized = SerializeItem(subitem, (((eq->slot_id-2500)*10)+2530+x+1), &sub_length, 0);
else
serialized = SerializeItem(subitem, eq->slot_id, &sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
if(normal_item)
{
data = new uchar[total_length+sub_length+4];
memcpy(data, tempdata, total_length);
*((uint32*)(data+total_length)) = x;
total_length += 4;
memcpy(data+total_length, serialized, sub_length);
total_length += sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
else
{
data = new uchar[total_length+sub_length];
memcpy(data, tempdata, total_length);
memcpy(data+total_length, serialized, sub_length);
total_length += sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
/*
for(int k = 0; k < MAX_AUGMENT_SLOTS; ++k)
{
serialized = NULL;
uint32 sub_sub_length = 0;
const ItemInst* subsubitem = (((const ItemInst*)eq->inst)eq->inst)->GetItem(k);
if(subsubitem)
{
serialized = SerializeItem(subsubitem, eq->slot_id, &sub_sub_length, 0);
if(serialized)
{
tempdata = data;
data = NULL;
data = new uchar[total_length+sub_sub_length+4];
memcpy(data, tempdata, total_length);
*((uint32*)(data+total_length)) = k;
total_length += 4;
memcpy(data+total_length, serialized, sub_sub_length);
total_length += sub_sub_length;
delete[] tempdata;
tempdata = NULL;
delete[] serialized;
serialized = NULL;
}
}
}
*/
}
}
}
}
}
else
{
_log(NET__ERROR, "Serialization failed on item slot %d during OP_CharInventory. Item skipped.",eq->slot_id);
}
}
in->size = total_length;
in->pBuffer = new unsigned char[in->size];
memcpy(in->pBuffer, data, in->size);
delete[] __emu_buffer;
_log(NET__ERROR, "Sending inventory to client");
_hex(NET__ERROR, in->pBuffer, in->size);
dest->FastQueuePacket(&in, ack_req);
}
Last, after the following line from the Item Serialization in SoF.cpp here:
itbs.unknown15 = 0xffffffff;
Add the following code:
uint8 aug_total = 0;
if(hdr.ItemClass == 0)
{
for(int x = 0; x < 5; ++x)
{
const ItemInst* subitem = ((const ItemInst*)inst)->GetItem(x);
if(subitem)
{
aug_total++;
}
}
}
itbs.augment_count = aug_total;
I think that is it. This should let you load a character that has augmented items as long as none of the augmented items are stored inside of a bag.