Browse Source

- Fix #515 display spawn name and database id when /spawn set or /spawn remove is used successfully.
- Fix #534 when drowning death occurs, proper kill message (kill blow type 10) is sent to clients for appropriate 'glug glug' message.
* AoM client WS_HearDeath structure fixed, blow type was in wrong place
- Addressed a number of memory leaks in handling of packet structures through configReader.getStruct and LoadPacketData
- Addressed buffer overflow of packets trying to match opcodes that do not exist (beyond bounds of the opcode list)
- Addressed issues with trying to read memory in packet data when a packet is not loaded correctly, where we should instead bypass and just delete the bogus packet (avoid crash)
- Tracking icon for DoF set to 231

Emagi 7 months ago
parent
commit
4d4873d674

+ 0 - 4
EQ2/source/WorldServer/ClientPacketFunctions.cpp

@@ -253,10 +253,6 @@ void ClientPacketFunctions::SendServerControlFlagsClassic(Client* client, int32
 void ClientPacketFunctions::SendServerControlFlags(Client* client, int8 param, int8 param_val, int8 value) {
 	PacketStruct* packet = configReader.getStruct("WS_ServerControlFlags", client->GetVersion());
 	if(packet) {
-		
-		if(client->GetVersion() <= 546 && param == 1 && !value) {
-			param_val = 0;
-		}
 		if (param == 1)
 			packet->setDataByName("parameter1", param_val);
 		else if (param == 2)

+ 7 - 5
EQ2/source/WorldServer/Commands/Commands.cpp

@@ -4910,11 +4910,11 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 							else if(set_type == SPAWN_SET_VALUE_LOCATION)
 							{
 								spawn->SetLocation(client->GetPlayer()->GetLocation());
-								client->Message(CHANNEL_COLOR_YELLOW, "Successfully set '%s' to '%u' for spawn '%s'", sep->arg[0], client->GetPlayer()->GetLocation(), name.c_str());
+								client->Message(CHANNEL_COLOR_YELLOW, "Successfully set '%s' to '%u' for spawn '%s' (DBID: %u)", sep->arg[0], client->GetPlayer()->GetLocation(), name.c_str(), spawn->GetDatabaseID());
 							}
 							else
 							{
-								client->Message(CHANNEL_COLOR_YELLOW, "Successfully set '%s' to '%s' for spawn '%s'", sep->arg[0], sep->arg[1], name.c_str());
+								client->Message(CHANNEL_COLOR_YELLOW, "Successfully set '%s' to '%s' for spawn '%s' (DBID: %u)", sep->arg[0], sep->arg[1], name.c_str(), spawn->GetDatabaseID());
 							}
 
 							switch (set_type)
@@ -4961,7 +4961,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 							{
 								if(spawn->GetSpawnLocationID() > 0 && database.UpdateSpawnLocationSpawns(spawn))
 								{
-									client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved spawn information.");
+									client->Message(CHANNEL_COLOR_YELLOW, "Successfully saved spawn information for spawn '%s' (DBID: %u)", name.c_str(), spawn->GetDatabaseID());
 								}
 								else if(spawn->GetSpawnLocationID() > 0)
 								{
@@ -4972,7 +4972,7 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 							{
 								if(spawn->GetDatabaseID() > 0 && database.SaveSpawnInfo(spawn))
 								{
-									client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully saved spawn.");
+									client->Message(CHANNEL_COLOR_YELLOW, "Successfully saved spawn for spawn '%s' (DBID: %u)", name.c_str(), spawn->GetDatabaseID());
 								}
 								else if(spawn->GetDatabaseID() > 0)
 								{
@@ -5027,9 +5027,11 @@ void Commands::Process(int32 index, EQ2_16BitString* command_parms, Client* clie
 			Spawn* spawn = cmdTarget;
 			if(spawn && !spawn->IsPlayer()){
 				if(spawn->GetSpawnLocationID() > 0){
+					string name = string(spawn->GetName());
+					int32 dbid = spawn->GetDatabaseID();
 					if(database.RemoveSpawnFromSpawnLocation(spawn)){
 						client->GetCurrentZone()->RemoveSpawn(spawn, true, false, true, true, true);
-						client->SimpleMessage(CHANNEL_COLOR_YELLOW, "Successfully removed spawn from zone");
+						client->Message(CHANNEL_COLOR_YELLOW, "Successfully removed spawn from zone for spawn '%s' (DBID: %u)", name.c_str(), dbid);
 					}
 					else
 						client->SimpleMessage(CHANNEL_COLOR_RED, "Error removing spawn, see console window for details.");

+ 1 - 1
EQ2/source/WorldServer/Player.cpp

@@ -6600,7 +6600,7 @@ void PlayerControlFlags::SendControlFlagUpdates(Client* client){
 						break;
 					}
 				}
-				ClientPacketFunctions::SendServerControlFlagsClassic(client, itr2->first, itr2->second);
+				ClientPacketFunctions::SendServerControlFlagsClassic(client, param, itr2->second);
 			}
 			else {
 				ClientPacketFunctions::SendServerControlFlags(client, itr->first, itr2->first, itr2->second);

+ 3 - 1
EQ2/source/WorldServer/Spawn.cpp

@@ -2523,14 +2523,16 @@ void Spawn::InitializeInfoPacketData(Player* spawn, PacketStruct* packet) {
 		}
 		
 		//Hide hood check
+		bool vis_hide_hood = false;
 		if (IsPlayer() && ((Player*)this)->get_character_flag(CF_HIDE_HOOD)) {
 			vis_flag += INFO_VIS_FLAG_HIDE_HOOD;
+			vis_hide_hood = true;
 		}
 		else if(IsPlayer()) {
 			classicFlags += INFO_CLASSIC_FLAG_SHOW_HOOD;
 		}
 		
-		if(appearance.hide_hood) {
+		if(!vis_hide_hood && appearance.hide_hood) {
 			vis_flag += INFO_VIS_FLAG_HIDE_HOOD;
 		}
 			

+ 1 - 1
EQ2/source/WorldServer/Spells.cpp

@@ -703,7 +703,7 @@ sint16 Spell::TranslateClientSpellIcon(int16 version) {
 	if(version <= 546) {
 		switch(spell_icon) {
 			case 772: // tracking
-				spell_icon = 32; // ??
+				spell_icon = 231; // ??
 				break;
 			case 773: // mining
 				spell_icon = 33; // OK

File diff suppressed because it is too large
+ 477 - 464
EQ2/source/WorldServer/client.cpp


+ 2 - 3
EQ2/source/WorldServer/zoneserver.cpp

@@ -2033,8 +2033,7 @@ void ZoneServer::ProcessDrowning(){
 		vector<Client*>::iterator itr;
 		for(itr = dead_list.begin(); itr != dead_list.end(); itr++){
 			RemoveDrowningVictim((*itr)->GetPlayer());
-			KillSpawn(false, (*itr)->GetPlayer(), 0);
-			(*itr)->SimpleMessage(CHANNEL_NARRATIVE, "You are sleeping with the fishes!  Glug, glug...");
+			KillSpawn(false, (*itr)->GetPlayer(), nullptr, true, 0, 0, 10); // kill blow type 10 means death by WATER! (glug glug!)
 		}
 	}
 }
@@ -4933,7 +4932,7 @@ void ZoneServer::KillSpawn(bool spawnListLocked, Spawn* dead, Spawn* killer, boo
 				packet->setDataByName("blow_type", kill_blow_type);
 
 				client->QueuePacket(packet->serialize());
-				LogWrite(COMBAT__DEBUG, 0, "Combat", "Zone Killing '%s'", dead->GetName());
+				LogWrite(COMBAT__DEBUG, 0, "Combat", "Zone Killing of '%s' by '%s' damage type %u, blow type %u", dead->GetName(), killer ? killer->GetName() : "", damage_type, kill_blow_type);
 				safe_delete(packet);
 			}
 		}

+ 5 - 4
EQ2/source/common/PacketStruct.cpp

@@ -1427,8 +1427,8 @@ bool PacketStruct::StructLoadData(DataStruct* data_struct, void* data, int32 len
 	}
 	case DATA_STRUCT_ARRAY: {
 		int32 size = GetArraySize(data_struct, 0);
-		if (size > 0xFFFF) {
-			LogWrite(PACKET__WARNING, 1, "Packet", "Possible corrupt packet while loading struct array, orig array size: %u in struct name %s, data name %s", size, GetName(), (data_struct && data_struct->GetName()) ? data_struct->GetName() : "??");
+		if (size > 0xFFFF || size > GetLoadLen()-GetLoadPos()) {
+			LogWrite(PACKET__WARNING, 1, "Packet", "Possible corrupt packet while loading struct array, orig array size: %u in struct name %s, data name %s, load_len %u, load_pos %u", size, GetName(), (data_struct && data_struct->GetName()) ? data_struct->GetName() : "??", GetLoadLen(), GetLoadPos());
 			return false;
 		}
 		PacketStruct* ps = GetPacketStructByName(data_struct->GetName());
@@ -1439,8 +1439,9 @@ bool PacketStruct::StructLoadData(DataStruct* data_struct, void* data, int32 len
 		}
 		if (ps && size > 0) {
 			//for(int i=0;i<size && (GetLoadLen()-GetLoadPos()) > 0;i++){
-			ps->LoadPacketData(GetLoadBuffer() + GetLoadPos(), GetLoadLen() - GetLoadPos());
-			SetLoadPos(GetLoadPos() + ps->GetLoadPos());
+			if(ps->LoadPacketData(GetLoadBuffer() + GetLoadPos(), GetLoadLen() - GetLoadPos())) {
+				SetLoadPos(GetLoadPos() + ps->GetLoadPos());
+			}
 			//}
 		}
 		break;

+ 22 - 4
EQ2/source/common/opcodemgr.cpp

@@ -130,12 +130,18 @@ bool OpcodeManager::LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s)
 
 //convenience routines
 const char *OpcodeManager::EmuToName(const EmuOpcode emu_op) {
+	if(emu_op > _maxEmuOpcode)
+		return "OP_Unknown";
+	
 	return(OpcodeNames[emu_op]);
 }
 
 const char *OpcodeManager::EQToName(const uint16 eq_op) {
 	//first must resolve the eq op to an emu op
 	EmuOpcode emu_op = EQToEmu(eq_op);
+	if(emu_op > _maxEmuOpcode)
+		return "OP_Unknown";
+	
 	return(OpcodeNames[emu_op]);
 }
 
@@ -227,7 +233,12 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
 	//opcode is checked for validity in GetEQOpcode
 	uint16 res;
 	MOpcodes.lock();
-	res = emu_to_eq[emu_op];
+	
+	if(emu_op > _maxEmuOpcode)
+		res = 0;
+	else
+		res = emu_to_eq[emu_op];
+	
 	MOpcodes.unlock();
 #ifdef _DEBUG_TRANSLATE
 	fprintf(stderr, "M Translate Emu %s (%d) to EQ 0x%.4x\n", OpcodeNames[emu_op], emu_op, res);
@@ -242,7 +253,10 @@ EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
 //		return(OP_Unknown);
 	EmuOpcode res;
 	MOpcodes.lock();
-	res = eq_to_emu[eq_op];
+	if(eq_op >= MAX_EQ_OPCODE)
+		res = OP_Unknown;
+	else
+		res = eq_to_emu[eq_op];
 	MOpcodes.unlock();
 #ifdef _DEBUG_TRANSLATE
 	fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
@@ -253,8 +267,12 @@ EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) {
 void RegularOpcodeManager::SetOpcode(EmuOpcode emu_op, uint16 eq_op) {
 	
 	//clear out old mapping
-	uint16 oldop = emu_to_eq[emu_op];
-	if(oldop != 0)
+	uint16 oldop = 0;
+	
+	if(emu_op <= _maxEmuOpcode)
+		 oldop = emu_to_eq[emu_op];
+	
+	if(oldop != 0 && oldop < MAX_EQ_OPCODE)
 		eq_to_emu[oldop] = OP_Unknown;
 	
 	//use our strategy, since we have it

+ 1 - 1
server/WorldStructs.xml

@@ -3184,8 +3184,8 @@ to zero and treated like placeholders." />
 <Struct Name="WS_HearDeath" ClientVersion="547" OpcodeName="OP_ClientCmdMsg" OpcodeType="OP_EqHearDeathCmd">
 <Data ElementName="attacker" Type="int32" />
 <Data ElementName="defender" Type="int32" />
-<Data ElementName="damage_type" Type="int8" />
 <Data ElementName="blow_type" Type="int16" />
+<Data ElementName="damage_type" Type="int8" />
 </Struct>
 <Struct Name="WS_UpdateSkillBook" ClientVersion="1" OpcodeName="OP_UpdateSkillBookMsg" >
 <Data ElementName="skill_count" Type="int16" />

Some files were not shown because too many files changed in this diff