void SpawnShell::zoneSpawns(const uint8_t* data, size_t len) { NetStream netStream(data,len); spawnStruct *spawn = new spawnStruct; uint32_t spawnStructSize; uint16_t parm1; while(!netStream.end()) { memset(spawn,0,sizeof(spawnStruct)); parm1=netStream.readUInt16NC(); if(parm1==0x1ff) parm1=netStream.readUInt16NC(); netStream.skipBytes(1); spawnStructSize=fillSpawnStruct(spawn,netStream.pos(),len,false); newSpawn(*spawn); netStream.skipBytes(spawnStructSize); } }
int32_t SpawnShell::fillSpawnStruct(spawnStruct *spawn, const uint8_t *data, size_t len, bool checkLen) { /* This reads data from the variable-length spawn struct */ NetStream netStream(data, len); int32_t retVal; uint32_t race; uint8_t i; QString name = netStream.readText(); if(name.length()) strcpy(spawn->name, name.latin1()); spawn->spawnId = netStream.readUInt32NC(); spawn->level = netStream.readUInt8(); // skip the next 4 bytes netStream.skipBytes(4); spawn->NPC = netStream.readUInt8(); spawn->miscData = netStream.readUInt32NC(); spawn->otherData = netStream.readUInt8(); // skip unknown3, unknown4 netStream.skipBytes(8); if(spawn->otherData & 1) { // it's a chest or untargetable do i = netStream.readUInt8(); while(i); do i = netStream.readUInt8(); while(i); do i = netStream.readUInt8(); while(i); // skip next 3 longs netStream.skipBytes(12); // next it loops through 9 longs, but we can just skip them netStream.skipBytes(36); // skip 1 byte netStream.skipBytes(1); // skip the last long netStream.skipBytes(4); } // skip facestyle, walk/run speeds, unknown5 netStream.skipBytes(13); spawn->race = netStream.readUInt32NC(); spawn->charProperties = netStream.readUInt8(); if(spawn->charProperties) { spawn->bodytype = netStream.readUInt32NC(); for(i = 1; i < spawn->charProperties; i++) { // extra character properties netStream.skipBytes(4); } } spawn->curHp = netStream.readUInt8(); // skip hair and face stuff netStream.skipBytes(18); spawn->holding = netStream.readUInt8(); spawn->deity = netStream.readUInt32NC(); spawn->guildID = netStream.readUInt32NC(); spawn->guildstatus = netStream.readUInt32NC(); spawn->class_ = netStream.readUInt8(); netStream.skipBytes(1); spawn->state = netStream.readUInt8(); spawn->light = netStream.readUInt8(); netStream.skipBytes(5); name = netStream.readText(); if(name.length()) { strcpy(spawn->lastName, name.latin1()); } netStream.skipBytes(5); spawn->petOwnerId = netStream.readUInt32NC(); netStream.skipBytes(25); spawn->posData[0] = netStream.readUInt32NC(); spawn->posData[1] = netStream.readUInt32NC(); spawn->posData[2] = netStream.readUInt32NC(); spawn->posData[3] = netStream.readUInt32NC(); spawn->posData[4] = netStream.readUInt32NC(); // skip color netStream.skipBytes(36); race = spawn->race; // this is how the client checks if equipment should be read. if(spawn->NPC == 0 || race <= 12 || race == 128 || race == 130 || race == 330 || race == 522) { for(i = 0; i < 9; i++) { spawn->equipment[i].itemId = netStream.readUInt32NC(); spawn->equipment[i].equip1 = netStream.readUInt32NC(); spawn->equipment[i].equip0 = netStream.readUInt32NC(); } } if(spawn->otherData & 4) { name = netStream.readText(); strcpy(spawn->title, name.latin1()); } if(spawn->otherData & 8) { name = netStream.readText(); strcpy(spawn->suffix, name.latin1()); } // unknowns netStream.skipBytes(8); spawn->isMercenary = netStream.readUInt8(); // unknowns netStream.skipBytes(28); // now we're at the end retVal = netStream.pos() - netStream.data(); if(checkLen && (int32_t)len != retVal) { seqDebug("SpawnShell::fillSpawnStruct - expected length: %d, read: %d for spawn '%s'", len, retVal, spawn->name); } return retVal; }
// same-name slots, connecting to Packet signals // this packet is variable in length. everything is dwords except the "idFile" field // which can be variable void SpawnShell::newGroundItem(const uint8_t* data, size_t len, uint8_t dir) { if (m_zoneMgr->isZoning()) return; if (dir != DIR_Server) return; if (!data) return; NetStream netStream(data, len); makeDropStruct ds; QString name; union { uint32_t n; float f; } x; memset(&ds, 0, sizeof(makeDropStruct)); // read drop id ds.dropId = netStream.readUInt32NC(); // read name name = netStream.readText(); if(name.length()) { strcpy(ds.idFile, name.latin1()); } // read past zone id netStream.readUInt32NC(); // read past zone instance netStream.readUInt32NC(); // read past unknown dword field netStream.readUInt32NC(); // read heading x.n = netStream.readUInt32NC(); ds.heading = x.f; // read past unknown dword field netStream.readUInt32NC(); // read past unknown dword field netStream.readUInt32NC(); // read past unknown dword field netStream.readUInt32NC(); // read y pos x.n = netStream.readUInt32NC(); ds.y = x.f; // read x pos x.n = netStream.readUInt32NC(); ds.x = x.f; // read z pos x.n = netStream.readUInt32NC(); ds.z = x.f; #ifdef SPAWNSHELL_DIAG seqDebug("SpawnShell::newGroundItem(makeDropStruct *)"); #endif Drop* item = (Drop*)m_drops.find(ds.dropId); if (item != NULL) { item->update(&ds, name); if (!showeq_params->fast_machine) item->setDistanceToPlayer(m_player->calcDist2DInt(*item)); else item->setDistanceToPlayer(m_player->calcDist(*item)); updateFilterFlags(item); item->updateLastChanged(); emit changeItem(item, tSpawnChangedALL); } else { item = new Drop(&ds, name); if (!showeq_params->fast_machine) item->setDistanceToPlayer(m_player->calcDist2DInt(*item)); else item->setDistanceToPlayer(m_player->calcDist(*item)); updateFilterFlags(item); m_drops.insert(ds.dropId, item); emit addItem(item); } }
void GroupMgr::groupUpdate(const uint8_t* data, size_t size) { // it's a variable-length packet depending on number of group members and length of names NetStream netStream(data, size); uint32_t memCount, memNumber, level; QString name; netStream.skipBytes(4); // number of group members memCount = netStream.readUInt32NC(); // leader name name = netStream.readText(); // reset counters m_memberCount = 0; m_membersInZoneCount = 0; emit cleared(); // update group member information for(uint32_t i = 0; i < memCount; i++) { memNumber = netStream.readUInt32NC(); name = netStream.readText(); netStream.skipBytes(3); level = netStream.readUInt32NC(); // copy the member name m_members[i]->m_name = name; // increment the member count m_memberCount++; // attempt to retrieve the member's spawn m_members[i]->m_spawn = m_spawnShell->findSpawnByName(m_members[i]->m_name); // incremement the spawn count if (m_members[i]->m_spawn) m_membersInZoneCount++; emit added(m_members[i]->m_name, m_members[i]->m_spawn); netStream.skipBytes(7); } // clear the rest for(uint32_t i = memCount; i < MAX_GROUP_MEMBERS; i++) { m_members[i]->m_name = ""; m_members[i]->m_spawn = 0; } // for debugging #if 0 for(uint32_t i = 0; i < MAX_GROUP_MEMBERS; i++) { if(!m_members[i]->m_name.isEmpty()) seqDebug("GroupMgr::groupUpdate '%s'", m_members[i]->m_name.latin1()); } #endif }
uint32_t SpawnShell::fillSpawnStruct(spawnStruct *spawn, const uint8_t *data, size_t len, bool checkLen) { NetStream netStream(data,len); QString name=netStream.readText(); if(name.length()) strcpy(spawn->name,name.latin1()); // seqDebug("name=%s",spawn->name); spawn->spawnId=netStream.readUInt32NC(); // seqDebug("id=%d (%x)",spawn->spawnId,spawn->spawnId); spawn->level=netStream.readUInt8(); // seqDebug("level=%d",spawn->level); // skip the next 4 bytes netStream.skipBytes(4); spawn->NPC=netStream.readUInt8(); // seqDebug("NPC=%d",spawn->NPC); spawn->miscData=netStream.readUInt32NC(); spawn->hasTitleOrSuffix=netStream.readUInt8(); // seqDebug("miscData: %x hasTitleOrSuffix: %x",spawn->miscData,spawn->hasTitleOrSuffix); // seqDebug("buyer=%d trader=%d TC=%d T=%d BB=%d LD=%d gen=%d anon=%d gm=%d invis=%d LFG=%d sneak=%d AFK=%d", // spawn->buyer,spawn->trader,spawn->targetcyclable,spawn->targetable,spawn->betabuffed, // spawn->linkdead,spawn->gender,spawn->anon,spawn->gm,spawn->invis,spawn->LFG,spawn->sneak,spawn->AFK); if(spawn->hasTitleOrSuffix & 1) { // it's a chest. skip usual 21 plus extra 56 netStream.skipBytes(77); } else { // skip facestyle, walk/run speeds, unknowns netStream.skipBytes(21); } spawn->race=netStream.readUInt32NC(); // seqDebug("race=%d",spawn->race); spawn->charProperties=netStream.readUInt8(); // seqDebug("charProperties=%d",spawn->charProperties); if(spawn->charProperties) { spawn->bodytype=netStream.readUInt32NC(); // seqDebug("bodytype=%d",spawn->bodytype); for(int i=1; i < spawn->charProperties; i++) { // extra character properties int j=netStream.readUInt32NC(); // netStream.skipBytes(4); } } spawn->curHp=netStream.readUInt8(); // seqDebug("curHp=%d",spawn->curHp); // skip hair and face stuff netStream.skipBytes(18); spawn->holding=netStream.readUInt8(); spawn->deity=netStream.readUInt32NC(); spawn->guildID=netStream.readUInt32NC(); spawn->guildstatus=netStream.readUInt32NC(); spawn->class_=netStream.readUInt8(); // seqDebug("holding=%d deity=%d guildID=%d guildstatus=%d class_=%d",spawn->holding, // spawn->deity,spawn->guildID,spawn->guildstatus,spawn->class_); netStream.skipBytes(1); spawn->state=netStream.readUInt8(); spawn->light=netStream.readUInt8(); netStream.skipBytes(5); name=netStream.readText(); if(name.length()) { strcpy(spawn->lastName,name.latin1()); // seqDebug("surname=%s",spawn->lastName); } netStream.skipBytes(5); spawn->petOwnerId=netStream.readUInt32NC(); // seqDebug("petOwnerId=%d",spawn->petOwnerId); netStream.skipBytes(25); spawn->posData[0]=netStream.readUInt32NC(); spawn->posData[1]=netStream.readUInt32NC(); spawn->posData[2]=netStream.readUInt32NC(); spawn->posData[3]=netStream.readUInt32NC(); spawn->posData[4]=netStream.readUInt32NC(); // seqDebug("%x %x %x %x %x",spawn->posData[0],spawn->posData[1],spawn->posData[2],spawn->posData[3],spawn->posData[4]); // seqDebug("%d %d %d | %d %d %d | %d %d | %d",spawn->y>>3,spawn->x>>3,spawn->z>>3, // spawn->deltaY>>2,spawn->deltaX>>2,spawn->deltaZ>>2, // spawn->heading,spawn->deltaHeading,spawn->animation); // skip color netStream.skipBytes(36); uint32_t race=spawn->race; // this is how the client checks if equipment should be read. if(spawn->NPC==0 || race <= 12 || race==128 || race==130 || race==330 || race==522) { for(int i=0; i<9; i++) { spawn->equipment[i].itemId=netStream.readUInt32NC(); spawn->equipment[i].equip1=netStream.readUInt32NC(); spawn->equipment[i].equip0=netStream.readUInt32NC(); } } if(spawn->hasTitleOrSuffix & 4) { name=netStream.readText(); strcpy(spawn->title,name.latin1()); // seqDebug("title=%s",spawn->title); } if(spawn->hasTitleOrSuffix & 8) { name=netStream.readText(); strcpy(spawn->suffix,name.latin1()); // seqDebug("suffix=%s",spawn->suffix); } netStream.skipBytes(32); // now we're at the end uint32_t retVal=netStream.pos()-netStream.data(); if(checkLen && (int32_t)len!=retVal) { seqDebug("SpawnShell::fillSpawnStruct - expected length: %d, read: %d",len,retVal); } return retVal; }
void GuildMgr::writeGuildList(const uint8_t* data, size_t len) { QFile guildsfile(guildsFileName); if (guildsfile.exists()) { if (!guildsfile.remove()) { seqWarn("GuildMgr: Could not remove old %s, unable to replace with server data!", guildsFileName.latin1()); return; } } if (!guildsfile.open(QIODevice::WriteOnly)) seqWarn("GuildMgr: Could not open %s for writing, unable to replace with server data!", guildsFileName.latin1()); QDataStream guildDataStream(&guildsfile); NetStream netStream(data, len); QString guildName; uint32_t size = 0; // to keep track of how much we're reading from the packet uint32_t guildId = 0; /* 0x48 in the packet starts the serialized list. See guildListStruct * and worldGuildListStruct in everquest.h */ // Skip the first guild in the list netStream.skipBytes(0x44); size += 0x44; while (!netStream.end()) { guildId = netStream.readUInt32NC(); guildName = netStream.readText(); size += 4; if (guildName.length()) { m_guildList[guildId] = guildName; // add guild name length, plus one for the null character size += guildName.length() + 1; } // theres an extra zero at the end of the packet if (size + 1 == len) break; } std::map<uint32_t, QString>::const_iterator it; for (it = m_guildList.begin(); it != m_guildList.end(); it++) { char szGuildName[64] = {0}; strcpy(szGuildName, it->second.latin1()); // seqDebug("GuildMgr::writeGuildList - add guild '%s' (%d)", szGuildName, it->first); guildDataStream.writeRawBytes(szGuildName, sizeof(szGuildName)); } guildsfile.close(); seqInfo("GuildMgr: New guildsfile written"); }