From 93f2affbf2f70c619cdc41b073dd19827df20448 Mon Sep 17 00:00:00 2001 From: Shauren Date: Sun, 13 Dec 2020 18:38:31 +0100 Subject: [PATCH] Core/Corpses: Fixed client crashes with player corpses Closes #25714 --- sql/base/characters_database.sql | 4 +++- .../master/2020_12_13_00_characters.sql | 3 +++ .../Implementation/CharacterDatabase.cpp | 4 ++-- src/server/game/Entities/Corpse/Corpse.cpp | 18 ++++++++++-------- src/server/game/Entities/Corpse/Corpse.h | 1 + .../Entities/Object/Updates/UpdateFields.cpp | 10 +++++----- .../Entities/Object/Updates/UpdateFields.h | 6 +++--- src/server/game/Entities/Player/Player.cpp | 1 + src/server/game/Maps/Map.cpp | 11 +++++------ 9 files changed, 33 insertions(+), 25 deletions(-) create mode 100644 sql/updates/characters/master/2020_12_13_00_characters.sql diff --git a/sql/base/characters_database.sql b/sql/base/characters_database.sql index 2e5b285cff..b2fe7bb0fb 100644 --- a/sql/base/characters_database.sql +++ b/sql/base/characters_database.sql @@ -1857,6 +1857,7 @@ CREATE TABLE `corpse` ( `displayId` int(10) unsigned NOT NULL DEFAULT '0', `itemCache` text NOT NULL, `race` tinyint(3) unsigned NOT NULL DEFAULT '0', + `class` tinyint(3) unsigned NOT NULL DEFAULT '0', `gender` tinyint(3) unsigned NOT NULL DEFAULT '0', `flags` tinyint(3) unsigned NOT NULL DEFAULT '0', `dynFlags` tinyint(3) unsigned NOT NULL DEFAULT '0', @@ -3820,7 +3821,8 @@ INSERT INTO `updates` VALUES ('2020_06_17_00_characters.sql','C3EE0D751E4B97CDF15F3BE27AAAE3646514A358','ARCHIVED','2020-06-17 17:04:56',0), ('2020_08_14_00_characters.sql','355685FF86EE64E2ED9D4B7D1311D53A9C2E0FA5','ARCHIVED','2020-08-14 21:41:24',0), ('2020_10_20_00_characters.sql','744F2A36865761920CE98A6DDE3A3BADF44D1E77','ARCHIVED','2020-10-20 21:36:49',0), -('2020_11_16_00_characters.sql','33D5C7539E239132923D01F4B6EAD5F3EF3EEB69','RELEASED','2020-11-16 19:16:31',0); +('2020_11_16_00_characters.sql','33D5C7539E239132923D01F4B6EAD5F3EF3EEB69','RELEASED','2020-11-16 19:16:31',0), +('2020_12_13_00_characters.sql','6AC743240033DED2C402ECB894A59D79EF607920','RELEASED','2020-12-13 18:36:58',0); /*!40000 ALTER TABLE `updates` ENABLE KEYS */; UNLOCK TABLES; diff --git a/sql/updates/characters/master/2020_12_13_00_characters.sql b/sql/updates/characters/master/2020_12_13_00_characters.sql new file mode 100644 index 0000000000..e0a3bb433e --- /dev/null +++ b/sql/updates/characters/master/2020_12_13_00_characters.sql @@ -0,0 +1,3 @@ +ALTER TABLE `corpse` ADD `class` tinyint(3) unsigned NOT NULL DEFAULT '0' AFTER `race`; + +UPDATE `corpse` SET `class`=(SELECT c.`class` FROM `characters` c WHERE c.`guid`=`guid`); diff --git a/src/server/database/Database/Implementation/CharacterDatabase.cpp b/src/server/database/Database/Implementation/CharacterDatabase.cpp index cbce793b1a..f779f3e884 100644 --- a/src/server/database/Database/Implementation/CharacterDatabase.cpp +++ b/src/server/database/Database/Implementation/CharacterDatabase.cpp @@ -421,8 +421,8 @@ void CharacterDatabaseConnection::DoPrepareStatements() PrepareStatement(CHAR_DEL_PLAYER_HOMEBIND, "DELETE FROM character_homebind WHERE guid = ?", CONNECTION_ASYNC); // Corpse - PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH); - PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, race, gender, flags, dynFlags, time, corpseType, instanceId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); + PrepareStatement(CHAR_SEL_CORPSES, "SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, class, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ?", CONNECTION_SYNCH); + PrepareStatement(CHAR_INS_CORPSE, "INSERT INTO corpse (guid, posX, posY, posZ, orientation, mapId, displayId, itemCache, race, class, gender, flags, dynFlags, time, corpseType, instanceId) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CORPSE, "DELETE FROM corpse WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_DEL_CORPSES_FROM_MAP, "DELETE cp, c FROM corpse_phases cp INNER JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?", CONNECTION_ASYNC); PrepareStatement(CHAR_SEL_CORPSE_PHASES, "SELECT cp.OwnerGuid, cp.PhaseId FROM corpse_phases cp LEFT JOIN corpse c ON cp.OwnerGuid = c.guid WHERE c.mapId = ? AND c.instanceId = ?", CONNECTION_SYNCH); diff --git a/src/server/game/Entities/Corpse/Corpse.cpp b/src/server/game/Entities/Corpse/Corpse.cpp index 299117ace9..77e9bcfa80 100644 --- a/src/server/game/Entities/Corpse/Corpse.cpp +++ b/src/server/game/Entities/Corpse/Corpse.cpp @@ -113,6 +113,7 @@ void Corpse::SaveToDB() stmt->setUInt32(index++, m_corpseData->DisplayID); // displayId stmt->setString(index++, items.str()); // itemCache stmt->setUInt8 (index++, m_corpseData->RaceID); // race + stmt->setUInt8 (index++, m_corpseData->Class); // class stmt->setUInt8 (index++, m_corpseData->Sex); // gender stmt->setUInt8 (index++, m_corpseData->Flags); // flags stmt->setUInt8 (index++, m_corpseData->DynamicFlags); // dynFlags @@ -165,8 +166,8 @@ void Corpse::DeleteFromDB(ObjectGuid const& ownerGuid, CharacterDatabaseTransact bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) { - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, race, gender, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, class, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? float posX = fields[0].GetFloat(); float posY = fields[1].GetFloat(); @@ -184,15 +185,16 @@ bool Corpse::LoadCorpseFromDB(ObjectGuid::LowType guid, Field* fields) SetItem(index, atoul(items[index])); SetRace(fields[7].GetUInt8()); - SetSex(fields[8].GetUInt8()); - SetFlags(fields[9].GetUInt8()); - SetCorpseDynamicFlags(CorpseDynFlags(fields[10].GetUInt8())); - SetOwnerGUID(ObjectGuid::Create(fields[14].GetUInt64())); + SetClass(fields[8].GetUInt8()); + SetSex(fields[9].GetUInt8()); + SetFlags(fields[10].GetUInt8()); + SetCorpseDynamicFlags(CorpseDynFlags(fields[11].GetUInt8())); + SetOwnerGUID(ObjectGuid::Create(fields[15].GetUInt64())); SetFactionTemplate(sChrRacesStore.AssertEntry(m_corpseData->RaceID)->FactionID); - m_time = time_t(fields[11].GetUInt32()); + m_time = time_t(fields[12].GetUInt32()); - uint32 instanceId = fields[13].GetUInt32(); + uint32 instanceId = fields[14].GetUInt32(); // place SetLocationInstanceId(instanceId); diff --git a/src/server/game/Entities/Corpse/Corpse.h b/src/server/game/Entities/Corpse/Corpse.h index fc3030ff2a..cbf57781fe 100644 --- a/src/server/game/Entities/Corpse/Corpse.h +++ b/src/server/game/Entities/Corpse/Corpse.h @@ -83,6 +83,7 @@ class TC_GAME_API Corpse : public WorldObject, public GridObject void SetGuildGUID(ObjectGuid guildGuid) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::GuildGUID), guildGuid); } void SetDisplayId(uint32 displayId) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::DisplayID), displayId); } void SetRace(uint8 race) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::RaceID), race); } + void SetClass(uint8 playerClass) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Class), playerClass); } void SetSex(uint8 sex) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Sex), sex); } void SetFlags(uint32 flags) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::Flags), flags); } void SetFactionTemplate(int32 factionTemplate) { SetUpdateFieldValue(m_values.ModifyValue(&Corpse::m_corpseData).ModifyValue(&UF::CorpseData::FactionTemplate), factionTemplate); } diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.cpp b/src/server/game/Entities/Object/Updates/UpdateFields.cpp index 6a7b62e93c..c6b75392e2 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.cpp +++ b/src/server/game/Entities/Object/Updates/UpdateFields.cpp @@ -4483,9 +4483,9 @@ void CorpseData::WriteCreate(ByteBuffer& data, EnumFlag fieldVi { data << uint32(Items[i]); } - data << uint8(Unused); data << uint8(RaceID); data << uint8(Sex); + data << uint8(Class); data << uint32(Customizations.size()); data << uint32(Flags); data << int32(FactionTemplate); @@ -4553,15 +4553,15 @@ void CorpseData::WriteUpdate(ByteBuffer& data, UpdateMask<33> const& changesMask } if (changesMask[7]) { - data << uint8(Unused); + data << uint8(RaceID); } if (changesMask[8]) { - data << uint8(RaceID); + data << uint8(Sex); } if (changesMask[9]) { - data << uint8(Sex); + data << uint8(Class); } if (changesMask[10]) { @@ -4596,9 +4596,9 @@ void CorpseData::ClearChangesMask() Base::ClearChangesMask(PartyGUID); Base::ClearChangesMask(GuildGUID); Base::ClearChangesMask(DisplayID); - Base::ClearChangesMask(Unused); Base::ClearChangesMask(RaceID); Base::ClearChangesMask(Sex); + Base::ClearChangesMask(Class); Base::ClearChangesMask(Flags); Base::ClearChangesMask(FactionTemplate); Base::ClearChangesMask(StateSpellVisualKitID); diff --git a/src/server/game/Entities/Object/Updates/UpdateFields.h b/src/server/game/Entities/Object/Updates/UpdateFields.h index 6d0998d631..35cd04e5bf 100644 --- a/src/server/game/Entities/Object/Updates/UpdateFields.h +++ b/src/server/game/Entities/Object/Updates/UpdateFields.h @@ -837,9 +837,9 @@ struct CorpseData : public IsUpdateFieldStructureTag, public HasChangesMask<33> UpdateField PartyGUID; UpdateField GuildGUID; UpdateField DisplayID; - UpdateField Unused; - UpdateField RaceID; - UpdateField Sex; + UpdateField RaceID; + UpdateField Sex; + UpdateField Class; UpdateField Flags; UpdateField FactionTemplate; UpdateField StateSpellVisualKitID; diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp index 860933b7c3..46ef5418b6 100644 --- a/src/server/game/Entities/Player/Player.cpp +++ b/src/server/game/Entities/Player/Player.cpp @@ -4437,6 +4437,7 @@ Corpse* Player::CreateCorpse() corpse->SetRace(getRace()); corpse->SetSex(GetNativeSex()); + corpse->SetClass(getClass()); corpse->SetCustomizations(Trinity::Containers::MakeIteratorPair(m_playerData->Customizations.begin(), m_playerData->Customizations.end())); corpse->SetFlags(flags); corpse->SetDisplayId(GetNativeDisplayId()); diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp index c77af89ae9..5d8c07dd2d 100644 --- a/src/server/game/Maps/Map.cpp +++ b/src/server/game/Maps/Map.cpp @@ -4789,8 +4789,8 @@ void Map::LoadCorpseData() stmt->setUInt32(0, GetId()); stmt->setUInt32(1, GetInstanceId()); - // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 - // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? + // 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + // SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, race, class, gender, flags, dynFlags, time, corpseType, instanceId, guid FROM corpse WHERE mapId = ? AND instanceId = ? PreparedQueryResult result = CharacterDatabase.Query(stmt); if (!result) return; @@ -4838,8 +4838,8 @@ void Map::LoadCorpseData() do { Field* fields = result->Fetch(); - CorpseType type = CorpseType(fields[12].GetUInt8()); - ObjectGuid::LowType guid = fields[14].GetUInt64(); + CorpseType type = CorpseType(fields[13].GetUInt8()); + ObjectGuid::LowType guid = fields[15].GetUInt64(); if (type >= MAX_CORPSE_TYPE || type == CORPSE_BONES) { TC_LOG_ERROR("misc", "Corpse (guid: " UI64FMTD ") have wrong corpse type (%u), not loading.", guid, type); @@ -4935,11 +4935,10 @@ Corpse* Map::ConvertCorpseToBones(ObjectGuid const& ownerGuid, bool insignia /*= bones->SetDisplayId(corpse->m_corpseData->DisplayID); bones->SetRace(corpse->m_corpseData->RaceID); bones->SetSex(corpse->m_corpseData->Sex); + bones->SetClass(corpse->m_corpseData->Class); bones->SetCustomizations(Trinity::Containers::MakeIteratorPair(corpse->m_corpseData->Customizations.begin(), corpse->m_corpseData->Customizations.end())); bones->SetFlags(corpse->m_corpseData->Flags | CORPSE_FLAG_BONES); bones->SetFactionTemplate(corpse->m_corpseData->FactionTemplate); - for (uint32 i = 0; i < EQUIPMENT_SLOT_END; ++i) - bones->SetItem(i, corpse->m_corpseData->Items[i]); bones->SetCellCoord(corpse->GetCellCoord()); bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());