Browse Source

DoF client work

- char create allows all races now, world list structure is fixed
- allows multi client to send world lists
- work in progress for character listings in DoF
Image 3 years ago
parent
commit
27fca1fae5

+ 22 - 9
EQ2/source/LoginServer/LWorld.cpp

@@ -753,7 +753,6 @@ LWorldList::LWorldList() {
 	else
 		OutLink = 0;
 
-	ServerListData = NULL;
 	UpdateServerList = true;
 	#ifdef WIN32
 		_beginthread(ServerUpdateLoop, 0, this);
@@ -1113,10 +1112,12 @@ vector<PacketStruct*>* LWorldList::GetServerListUpdate(int16 version){
 EQ2Packet* LWorldList::MakeServerListPacket(int8 lsadmin, int16 version) {
 
 	// if the latest world list has already been loaded, just return the string
-	if(!UpdateServerList && ServerListData)
-		return ServerListData;
-	
 	MWorldMap.readlock();
+	if (!UpdateServerList && ServerListData.count(version))
+	{
+		MWorldMap.releasereadlock();
+		return ServerListData[version];
+	}
 
 	LWorld* world = 0;
 	uchar num_servers[2];
@@ -1148,8 +1149,8 @@ EQ2Packet* LWorldList::MakeServerListPacket(int8 lsadmin, int16 version) {
 			ServerNum++;
 			packet->setArrayDataByName("id", world->GetID(), ServerNum-1);
 
-			if (version < 1096)
-				packet->setDataByName("allowed_races", 0x0007FFFF, ServerNum - 1); // no Freeblood and Aerakyn race
+			if (version < 1212)
+				packet->setArrayDataByName("allowed_races", 0xFFFFFFFF, ServerNum - 1);
 			else if (version < 60006)
 				packet->setArrayDataByName("allowed_races", 0x000FFFFF, ServerNum - 1); // + Freeblood
 			else
@@ -1160,6 +1161,7 @@ EQ2Packet* LWorldList::MakeServerListPacket(int8 lsadmin, int16 version) {
 			packet->setArrayDataByName("name", world->GetName(), ServerNum-1);
 			packet->setArrayDataByName("name2", world->GetName(), ServerNum-1);
 			packet->setArrayDataByName("feature_set",0, ServerNum-1);
+
 			packet->setArrayDataByName("load", world->GetWorldStatus(), ServerNum-1);
 			if(world->IsLocked())
 				packet->setArrayDataByName("locked", 1, ServerNum - 1);
@@ -1168,17 +1170,28 @@ EQ2Packet* LWorldList::MakeServerListPacket(int8 lsadmin, int16 version) {
 				packet->setArrayDataByName("tag", 0, ServerNum - 1);
 			else
 				packet->setArrayDataByName("tag", 1, ServerNum - 1);
+
+			if ( version < 1212 )
+				packet->setArrayDataByName("unknown", ServerNum, ServerNum - 1);
 		}
 	}
 
 	EQ2Packet* pack = packet->serialize();
-	safe_delete(ServerListData);
-	ServerListData = pack;
+	printf("WorldList:\n");
+	DumpPacket(pack->pBuffer, pack->size);
+	if (ServerListData.count(version))
+	{
+		map<int32, EQ2Packet*>::iterator it = ServerListData.find(version);
+		EQ2Packet* tmpPack = ServerListData[version];
+		safe_delete(tmpPack);
+		ServerListData.erase(it);
+	}
+	ServerListData.insert(make_pair(version, pack));
 	MWorldMap.releasereadlock();
 
 	SetUpdateServerList( false );
 
-	return ServerListData;
+	return ServerListData[version];
 }
 
 void LWorldList::SendWorldStatus(LWorld* chat, char* adminname) {

+ 1 - 1
EQ2/source/LoginServer/LWorld.h

@@ -212,7 +212,7 @@ private:
 
 	// holds the world server list so we don't have to create it for every character
 	// logging in
-	EQ2Packet* ServerListData;
+	map<int32,EQ2Packet*> ServerListData;
 	bool UpdateServerList;
 };
 #endif

+ 41 - 11
EQ2/source/LoginServer/LoginDatabase.cpp

@@ -32,16 +32,20 @@ extern LoginDatabase database;
 extern LWorldList world_list;
 
 
-void LoginDatabase::SetZoneInformation(int32 server_id, int32 zone_id, PacketStruct* packet){	
+void LoginDatabase::SetZoneInformation(int32 server_id, int32 zone_id, int32 version, PacketStruct* packet){	
 	if(packet){
 		Query query;
-		MYSQL_RES* result = query.RunQuery2(Q_SELECT, "SELECT name, description from ls_world_zones where server_id=%i and zone_id=%i", server_id, zone_id);
+		MYSQL_RES* result = 0;
+		
+		if ( version >= 1212 )
+			result = query.RunQuery2(Q_SELECT, "SELECT name, description from ls_world_zones where server_id=%i and zone_id=%i", server_id, zone_id);
+
 		MYSQL_ROW row;
 		if(result && (row = mysql_fetch_row(result))) {
-			if(row[0])
-				packet->setMediumStringByName("zone", row[0]);
-			else
-				packet->setMediumStringByName("zone", " ");
+				if (row[0])
+					packet->setMediumStringByName("zone", row[0]);
+				else
+					packet->setMediumStringByName("zone", " ");
 			if(row[1])
 				packet->setMediumStringByName("zonedesc", row[1]);
 			else
@@ -49,13 +53,39 @@ void LoginDatabase::SetZoneInformation(int32 server_id, int32 zone_id, PacketStr
 		}
 		else{
 			Query query2;
-			MYSQL_RES* result2 = query2.RunQuery2(Q_SELECT, "SELECT name, description from zones where id=%i", zone_id);
+			MYSQL_RES* result2 = 0;
+
+			if (version < 1212)
+				result2 = query2.RunQuery2(Q_SELECT, "SELECT file, description from zones where id=%i", zone_id);
+			else
+				result2 = query2.RunQuery2(Q_SELECT, "SELECT name, description from zones where id=%i", zone_id);
+
 			MYSQL_ROW row2;
 			if(result2 && (row2 = mysql_fetch_row(result2))) {
-				if(row2[0])
-					packet->setMediumStringByName("zone", row2[0]);
+
+				if (version < 1212)
+				{
+					if (row2[0])
+					{
+						int len = strlen(row2[0]);
+						char* zoneName = new char[len + 2];
+						strncpy(zoneName, row2[0], len);
+						zoneName[len] = 0x2E;
+						zoneName[len + 1] = 0x30;
+
+						packet->setMediumStringByName("zone", zoneName);
+						safe_delete_array(zoneName);
+					}
+					else
+						packet->setMediumStringByName("zone", ".0");
+				}
 				else
-					packet->setMediumStringByName("zone", " ");
+				{
+					if (row2[0])
+						packet->setMediumStringByName("zone", row2[0]);
+					else
+						packet->setMediumStringByName("zone", " ");
+				}
 				if(row2[1])
 					packet->setMediumStringByName("zonedesc", row2[1]);
 				else
@@ -124,7 +154,7 @@ void LoginDatabase::LoadCharacters(LoginAccount* acct, int16 version){
 			player->packet->setDataByName("deity", atoi(row[6]));
 			player->packet->setDataByName("body_size", atof(row[7]));
 			player->packet->setDataByName("body_age", atof(row[8]));
-			SetZoneInformation(atoi(row[1]), atoi(row[9]), player->packet);
+			SetZoneInformation(atoi(row[1]), atoi(row[9]), version, player->packet);
 			player->packet->setDataByName("level", atoi(row[10]));
 			player->packet->setDataByName("soga_wing_type", atoi(row[11]));
 			player->packet->setDataByName("soga_chest_type", atoi(row[12]));

+ 1 - 1
EQ2/source/LoginServer/LoginDatabase.h

@@ -67,7 +67,7 @@ public:
 	TableQuery* GetLatestTableQuery(int32 server_ip, char* name, int16 version);
 	bool VerifyDataTable(char* name);
 	sint16 GetDataVersion(char* name);
-	void SetZoneInformation(int32 server_id, int32 zone_id, PacketStruct* packet);
+	void SetZoneInformation(int32 server_id, int32 zone_id, int32 version, PacketStruct* packet);
 	string GetZoneDescription(char* name);
 	string GetColumnNames(char* name);
 	TableDataQuery* GetTableDataQuery(int32 server_ip, char* name, int16 version);

+ 5 - 2
EQ2/source/LoginServer/client.cpp

@@ -176,7 +176,7 @@ bool Client::Process() {
 						safe_delete(packet);
 						packet = configReader.getStruct("LS_LoginRequest", 1212);
 						if (packet->LoadPacketData(app->pBuffer, app->size)) {
-							version = packet->getType_int32_ByName("version");
+							version = packet->getType_int16_ByName("version");
 						}
 					}
 					//[7:19 PM] Kirmmin: Well, I very quickly learned that unknown3 in LS_LoginRequest packet is the same value as cl_eqversion in the eq2_defaults.ini file.
@@ -279,6 +279,7 @@ bool Client::Process() {
 					LWorld* world_server = world_list.FindByID(packet->getType_int32_ByName("server_id"));
 					if(!world_server)
 					{
+						DumpPacket(app->pBuffer, app->size);
 						cout << GetAccountName() << " attempted creation of character with an invalid server id of: " << packet->getType_int32_ByName("server_id") << "\n";
 						break;
 					}
@@ -508,7 +509,7 @@ void Client::SendCharList(){
 	LS_CharSelectList list;
 	list.loadData(GetAccountID(), GetLoginAccount()->charlist, GetVersion()); 
 	EQ2Packet* outapp = list.serialize(GetVersion());
-//	DumpPacket(outapp);
+	DumpPacket(outapp->pBuffer, outapp->size);
 	QueuePacket(outapp);
 
 }
@@ -560,6 +561,8 @@ void Client::SendLoginAccepted() {
 		packet->setDataByName("unknown8", 0xFF, 1);
 
 		EQ2Packet* outapp = packet->serialize();
+		printf("Out struct:\n");
+		DumpPacket(outapp->pBuffer, outapp->size);
 		QueuePacket(outapp);
 		safe_delete(packet);
 	}

+ 162 - 0
server/CommonStructs.xml

@@ -82,6 +82,87 @@ to zero and treated like placeholders." />
 <Data ElementName="soga_body_size" Type="float" Size="1" />
 <Data ElementName="soga_body_age" Type="float" Size="1" />
 </Struct>
+<Struct Name="CreateCharacter" ClientVersion="546" OpcodeName="OP_CreateCharacterRequestMsg">
+<Data ElementName="unknown0" Type="int8" />
+<Data ElementName="unknown1" Type="int32" />
+<Data ElementName="unknown2" Type="int32" />
+<Data ElementName="server_id" Type="int32" />
+<Data ElementName="name" Type="EQ2_16Bit_String" />
+<Data ElementName="race" Type="int8" />
+<Data ElementName="gender" Type="int8" />
+<Data ElementName="deity" Type="int8" />
+<Data ElementName="class" Type="int8" />
+<Data ElementName="level" Type="int8" />
+<Data ElementName="starting_zone" Type="int8" />
+<Data ElementName="version" Type="int8" />
+<Data ElementName="race_file" Type="EQ2_16Bit_String" />
+<Data ElementName="skin_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="skin_color2" Type="EQ2_Color" Size="1" />
+<Data ElementName="eye_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="hair_color1" Type="EQ2_Color" Size="1" />
+<Data ElementName="hair_color2" Type="EQ2_Color" Size="1" />
+<Data ElementName="hair_highlight" Type="EQ2_Color" Size="1" />
+<Data ElementName="unknown8" Type="int8" Size="26" />
+<Data ElementName="hair_file" Type="EQ2_16Bit_String" />
+<Data ElementName="hair_type_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="hair_type_highlight_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="face_file" Type="EQ2_16Bit_String" />
+<Data ElementName="hair_face_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="hair_face_highlight_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="wing_file" Type="EQ2_16Bit_String" />
+<Data ElementName="wing_color1" Type="EQ2_Color" Size="1" />
+<Data ElementName="wing_color2" Type="EQ2_Color" Size="1" />
+<Data ElementName="chest_file" Type="EQ2_16Bit_String" />
+<Data ElementName="shirt_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="unknown_chest_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="legs_file" Type="EQ2_16Bit_String" />
+<Data ElementName="pants_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="unknown_legs_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="unknown9" Type="EQ2_Color" Size="1" />
+<Data ElementName="eyes2" Type="float" Size="3" />
+<Data ElementName="ears" Type="float" Size="3" />
+<Data ElementName="eye_brows" Type="float" Size="3" />
+<Data ElementName="cheeks" Type="float" Size="3" />
+<Data ElementName="lips" Type="float" Size="3" />
+<Data ElementName="chin" Type="float" Size="3" />
+<Data ElementName="nose" Type="float" Size="3" />
+<Data ElementName="body_size" Type="float" Size="1" />
+<Data ElementName="body_age" Type="float" Size="1" />
+<Data ElementName="soga_version" Type="int8" />
+<Data ElementName="soga_race_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_skin_color" Type="EQ2_Color" />
+<Data ElementName="soga_eye_color" Type="EQ2_Color" />
+<Data ElementName="soga_hair_color1" Type="EQ2_Color" />
+<Data ElementName="soga_hair_color2" Type="EQ2_Color" />
+<Data ElementName="soga_hair_highlight" Type="EQ2_Color" />
+<Data ElementName="soga_unknown_color1" Type="EQ2_Color" />
+<Data ElementName="soga_unknown11" Type="int8" Size="26" />
+<Data ElementName="soga_hair_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_hair_type_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_hair_type_highlight_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_face_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_hair_face_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_hair_face_highlight_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_wing_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_wing_color1" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_wing_color2" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_chest_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_shirt_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_unknown_chest_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_legs_file" Type="EQ2_16Bit_String" />
+<Data ElementName="soga_pants_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_unknown_legs_color" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_unknown12" Type="EQ2_Color" Size="1" />
+<Data ElementName="soga_eyes2" Type="float" Size="3" />
+<Data ElementName="soga_ears" Type="float" Size="3" />
+<Data ElementName="soga_eye_brows" Type="float" Size="3" />
+<Data ElementName="soga_cheeks" Type="float" Size="3" />
+<Data ElementName="soga_lips" Type="float" Size="3" />
+<Data ElementName="soga_chin" Type="float" Size="3" />
+<Data ElementName="soga_nose" Type="float" Size="3" />
+<Data ElementName="soga_body_size" Type="float" Size="1" />
+<Data ElementName="soga_body_age" Type="float" Size="1" />
+</Struct>
 <Struct Name="CreateCharacter" ClientVersion="869" OpcodeName="OP_CreateCharacterRequestMsg">
 <Data ElementName="unknown0" Type="int8" />
 <Data ElementName="unknown1" Type="int32" />
@@ -499,6 +580,87 @@ to zero and treated like placeholders." />
 	<Data ElementName="soga_body_age" Type="float" />
 	<Data ElementName="unknown13" Type="int8" Size="2" />
 </Struct>
+<Struct Name="CreateCharacter" ClientVersion="65534" OpcodeName="OP_CreateCharacterRequestMsg" >
+	<Data ElementName="unknown0" Type="int8" />
+	<Data ElementName="unknown1" Type="int32" />
+	<Data ElementName="account_id" Type="int32" />
+	<Data ElementName="unknown3" Type="int8" />
+	<Data ElementName="server_id" Type="int32" />
+	<Data ElementName="name" Type="EQ2_16Bit_String" />
+	<Data ElementName="race" Type="int8" />
+	<Data ElementName="gender" Type="int8" />
+	<Data ElementName="deity" Type="int8" />
+	<Data ElementName="class" Type="int8" />
+	<Data ElementName="level" Type="int8" />
+	<Data ElementName="starting_zone" Type="int32" />
+	<Data ElementName="version" Type="int8" />
+	<Data ElementName="race_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="skin_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="skin_color2" Type="EQ2_Color" Size="1" />
+	<Data ElementName="eye_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="hair_color1" Type="EQ2_Color" Size="1" />
+	<Data ElementName="hair_color2" Type="EQ2_Color" Size="1" />
+	<Data ElementName="unknown8" Type="int8" Size="38" />
+	<Data ElementName="hair_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="hair_type_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="hair_type_highlight_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="face_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="hair_face_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="hair_face_highlight_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="wing_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="wing_color1" Type="EQ2_Color" Size="1" />
+	<Data ElementName="wing_color2" Type="EQ2_Color" Size="1" />
+	<Data ElementName="chest_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="shirt_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="unknown_chest_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="legs_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="pants_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="unknown_legs_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="unknown9" Type="EQ2_Color" Size="1" />
+	<Data ElementName="eyes2" Type="float" Size="3" />
+	<Data ElementName="ears" Type="float" Size="3" />
+	<Data ElementName="eye_brows" Type="float" Size="3" />
+	<Data ElementName="cheeks" Type="float" Size="3" />
+	<Data ElementName="lips" Type="float" Size="3" />
+	<Data ElementName="chin" Type="float" Size="3" />
+	<Data ElementName="nose" Type="float" Size="3" />
+	<Data ElementName="body_size" Type="float" />
+	<Data ElementName="body_age" Type="float" />
+	<Data ElementName="soga_version" Type="int8" />
+	<Data ElementName="soga_race_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_skin_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_eye_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_hair_color1" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_hair_color2" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_hair_highlight" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_unknown11" Type="int8" Size="38" />
+	<Data ElementName="soga_hair_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_hair_type_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_hair_type_highlight_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_face_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_hair_face_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_hair_face_highlight_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_wing_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_wing_color1" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_wing_color2" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_chest_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_shirt_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_unknown_chest_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_legs_file" Type="EQ2_16Bit_String" />
+	<Data ElementName="soga_pants_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_unknown_legs_color" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_unknown12" Type="EQ2_Color" Size="1" />
+	<Data ElementName="soga_eyes2" Type="float" Size="3" />
+	<Data ElementName="soga_ears" Type="float" Size="3" />
+	<Data ElementName="soga_eye_brows" Type="float" Size="3" />
+	<Data ElementName="soga_cheeks" Type="float" Size="3" />
+	<Data ElementName="soga_lips" Type="float" Size="3" />
+	<Data ElementName="soga_chin" Type="float" Size="3" />
+	<Data ElementName="soga_nose" Type="float" Size="3" />
+	<Data ElementName="soga_body_size" Type="float" />
+	<Data ElementName="soga_body_age" Type="float" />
+	<Data ElementName="unknown13" Type="int8" Size="2" />
+</Struct>
 <Struct Name="BadLanguageFilter" ClientVersion="1" OpcodeName="OP_BadLanguageFilter">
 <Data ElementName="num_words" Type="int16" OversizedValue="255" />
 <Data ElementName="words_array" Type="Array" ArraySizeVariable="num_words">

+ 137 - 3
server/LoginStructs.xml

@@ -51,9 +51,11 @@ to zero and treated like placeholders." />
 <Data ElementName="password" Type="EQ2_16Bit_String" />
 <Data ElementName="unknown2" Type="int8" Size="8" />
 <Data ElementName="unknown3" Type="int8" Size="2" />
-<Data ElementName="version" Type="int32" />
-<Data ElementName="unknown3" Type="int16" />
-<Data ElementName="unknown4" Type="int32" />
+<Data ElementName="version" Type="int16" />
+<Data ElementName="unknown4" Type="int8" />
+<Data ElementName="unknown5" Type="int32" Size="3" />
+<Data ElementName="unknown6" Type="int16" />
+<Data ElementName="unknown7" Type="EQ2_16Bit_String" />
 </Struct>
 <!--<Struct Name="LS_WorldList" ClientVersion="1" OpcodeName="OP_WorldListMsg">
 <Data ElementName="num_worlds" Type="int8" />
@@ -90,6 +92,58 @@ to zero and treated like placeholders." />
 </Data>
 <Data ElementName="unknown2" Type="int8" />
 </Struct>
+<Struct Name="LS_WorldList" ClientVersion="546" OpcodeName="OP_WorldListMsg">
+<Data ElementName="num_worlds" Type="int8" />
+<Data ElementName="world_list" Type="Array" ArraySizeVariable="num_worlds">
+  <Data ElementName="id" Type="int32" Size="1" />
+  <Data ElementName="name" Type="EQ2_16Bit_String" />
+  <Data ElementName="name2" Type="EQ2_16Bit_String" />
+  <Data ElementName="tag" Type="int8" Size="1" />
+  <Data ElementName="locked" Type="int8" Size="1" />
+  <Data ElementName="hidden" Type="int8" Size="1" />
+  <Data ElementName="unknown" Type="int8" Size="1" />
+  <Data ElementName="num_players" Type="int16" Size="1" />
+  <Data ElementName="load" Type="int8" Size="1" />
+  <Data ElementName="number_online_flag" Type="int8" Size="1" />
+  <Data ElementName="allowed_races" Type="int32" Size="1" />
+</Data>
+</Struct>
+<Struct Name="LS_WorldList" ClientVersion="547" OpcodeName="OP_WorldListMsg">
+<Data ElementName="num_worlds" Type="int8" />
+<Data ElementName="world_list" Type="Array" ArraySizeVariable="num_worlds">
+  <Data ElementName="id" Type="int32" Size="1" />
+  <Data ElementName="name" Type="EQ2_16Bit_String" />
+  <Data ElementName="name2" Type="EQ2_16Bit_String" />
+  <Data ElementName="tag" Type="int8" Size="1" />
+  <Data ElementName="locked" Type="int8" Size="1" />
+  <Data ElementName="hidden" Type="int8" Size="1" />
+  <Data ElementName="unknown" Type="int8" Size="1" />
+  <Data ElementName="num_players" Type="int16" Size="1" />
+  <Data ElementName="load" Type="int8" Size="1" />
+  <Data ElementName="number_online_flag" Type="int8" Size="1" />
+  <Data ElementName="feature_set" Type="int8" Size="2" />
+  <Data ElementName="allowed_races" Type="int32" Size="1" />
+</Data>
+<Data ElementName="unknown2" Type="int8" />
+</Struct>
+<Struct Name="LS_WorldList" ClientVersion="60114" OpcodeName="OP_WorldListMsg">
+<Data ElementName="num_worlds" Type="int8" />
+<Data ElementName="world_list" Type="Array" ArraySizeVariable="num_worlds">
+  <Data ElementName="id" Type="int32" Size="1" />
+  <Data ElementName="name" Type="EQ2_16Bit_String" />
+  <Data ElementName="name2" Type="EQ2_16Bit_String" />
+  <Data ElementName="tag" Type="int8" Size="1" />
+  <Data ElementName="locked" Type="int8" Size="1" />
+  <Data ElementName="hidden" Type="int8" Size="1" />
+  <Data ElementName="unknown" Type="int8" Size="1" />
+  <Data ElementName="num_players" Type="int16" Size="1" />
+  <Data ElementName="load" Type="int8" Size="1" />
+  <Data ElementName="number_online_flag" Type="int8" Size="1" />
+  <Data ElementName="feature_set" Type="int8" Size="2" />
+  <Data ElementName="allowed_races" Type="int32" Size="1" />
+</Data>
+<Data ElementName="unknown2" Type="int8" />
+</Struct>
 <Struct Name="LS_WorldList" ClientVersion="65534" OpcodeName="OP_WorldListMsg">
 <Data ElementName="num_worlds" Type="int8" />
 <Data ElementName="world_list" Type="Array" ArraySizeVariable="num_worlds">
@@ -231,6 +285,86 @@ to zero and treated like placeholders." />
 <Data ElementName="soga_hair_face_highlight_color" Type="EQ2_Color" />
 <Data ElementName="unknown15" Type="int8" Size="7" />
 </Struct>
+<Struct Name="CharSelectProfile" ClientVersion="546">
+<Data ElementName="charid" Type="int32" Size="1" />
+<Data ElementName="server_id" Type="int32" Size="1" />
+<Data ElementName="name" Type="EQ2_16BitString" Size="1" />
+<Data ElementName="race" Type="int8" Size="1" />
+<Data ElementName="class" Type="int8" Size="1" />
+<!--<Data ElementName="gender" Type="int8" Size="1" />-->
+<Data ElementName="level" Type="int32" Size="1" />
+<Data ElementName="zone" Type="EQ2_16BitString" Size="1" />
+<Data ElementName="unknown1" Type="int32" Size="1" />
+<Data ElementName="unknown2" Type="int32" Size="1" />
+<Data ElementName="created_date" Type="int32" Size="1" />
+<Data ElementName="last_played" Type="int32" Size="1" />
+<Data ElementName="unknown3" Type="int32" Size="1" />
+<Data ElementName="unknown4" Type="int32" Size="1" />
+<Data ElementName="zonename2" Type="EQ2_16BitString" Size="1" />
+<Data ElementName="zonedesc" Type="EQ2_16BitString" Size="1" />
+<!-- need to work further down at this point things are off! -->
+<Data ElementName="unknown5" Type="int32" Size="1" />
+<Data ElementName="account_id" Type="int32" Size="1" />
+<Data ElementName="unknown6" Type="int8" Size="2" />
+<Data ElementName="unknown7" Type="int32" Size="1" />
+<Data ElementName="tradeskill_class" Type="int8" Size="1" />
+<Data ElementName="tradeskill_level" Type="int32" Size="1" />
+<Data ElementName="unknown8" Type="int8" Size="1" />
+<Data ElementName="race_type" Type="int16" Size="1" />
+<Data ElementName="skin_color" Type="EQ2_Color" />
+<Data ElementName="eye_color" Type="EQ2_Color" />
+<Data ElementName="equip" Type="EQ2_EquipmentItem" Size="25" />
+<Data ElementName="hair_type" Type="int16" Size="1" />
+<Data ElementName="hair_type_color" Type="EQ2_Color" />
+<Data ElementName="hair_type_highlight_color" Type="EQ2_Color" />
+<Data ElementName="hair_face_type" Type="int16" Size="1" />
+<Data ElementName="hair_face_color" Type="EQ2_Color" />
+<Data ElementName="hair_face_highlight_color" Type="EQ2_Color" />
+<Data ElementName="wing_type" Type="int16" Size="1" />
+<Data ElementName="wing_color1" Type="EQ2_Color" />
+<Data ElementName="wing_color2" Type="EQ2_Color" />
+<Data ElementName="chest_type" Type="int16" Size="1" />
+<Data ElementName="shirt_color" Type="EQ2_Color" />
+<Data ElementName="unknown_chest_color" Type="EQ2_Color" />
+<Data ElementName="legs_type" Type="int16" Size="1" />
+<Data ElementName="pants_color" Type="EQ2_Color" />
+<Data ElementName="unknown_legs_color" Type="EQ2_Color" />
+<Data ElementName="unknown9" Type="EQ2_Color" />
+<Data ElementName="eye_type" Type="sint8" Size="3" />
+<Data ElementName="ear_type" Type="sint8" Size="3" />
+<Data ElementName="eye_brow_type" Type="sint8" Size="3" />
+<Data ElementName="cheek_type" Type="sint8" Size="3" />
+<Data ElementName="lip_type" Type="sint8" Size="3" />
+<Data ElementName="chin_type" Type="sint8" Size="3" />
+<Data ElementName="nose_type" Type="sint8" Size="3" />
+<Data ElementName="body_size" Type="sint8" Size="1" />
+<Data ElementName="unknown10" Type="int8" Size="9" />
+<Data ElementName="hair_color1" Type="EQ2_Color" />
+<Data ElementName="hair_color2" Type="EQ2_Color" />
+<Data ElementName="unknown11" Type="int8" Size="13" />
+<Data ElementName="soga_race_type" Type="int16" Size="1" />
+<Data ElementName="soga_skin_color" Type="EQ2_Color" />
+<Data ElementName="soga_eye_color" Type="EQ2_Color" />
+<Data ElementName="Unknown12" Type="int8" Size="3" />
+<Data ElementName="soga_eye_type" Type="sint8" Size="3" />
+<Data ElementName="soga_ear_type" Type="sint8" Size="3" />
+<Data ElementName="soga_eye_brow_type" Type="sint8" Size="3" />
+<Data ElementName="soga_cheek_type" Type="sint8" Size="3" />
+<Data ElementName="soga_lip_type" Type="sint8" Size="3" />
+<Data ElementName="soga_chin_type" Type="sint8" Size="3" />
+<Data ElementName="soga_nose_type" Type="sint8" Size="3" />
+<Data ElementName="unknown13" Type="int16" Size="1" />
+<Data ElementName="soga_hair_color1" Type="EQ2_Color"  />
+<Data ElementName="soga_hair_color2" Type="EQ2_Color"  />
+<Data ElementName="unknown14" Type="EQ2_Color" />
+<Data ElementName="soga_hair_type" Type="int16" Size="1" />
+<Data ElementName="soga_hair_type_color" Type="EQ2_Color" />
+<Data ElementName="soga_hair_type_highlight_color" Type="EQ2_Color" />
+<Data ElementName="soga_hair_face_type" Type="int16" Size="1" />
+<Data ElementName="soga_hair_face_color" Type="EQ2_Color" />
+<Data ElementName="soga_hair_face_highlight_color" Type="EQ2_Color" />
+<Data ElementName="unknown15" Type="int8" Size="7" />
+</Struct>
 <Struct Name="CharSelectProfile" ClientVersion="887">
 <Data ElementName="version" Type="int32" Size="1" />
 <Data ElementName="charid" Type="int32" Size="1" />