Core/Corpses: Fixed client crashes with player corpses

Closes #25714
This commit is contained in:
Shauren
2020-12-13 18:38:31 +01:00
parent 015666b044
commit 93f2affbf2
9 changed files with 33 additions and 25 deletions

View File

@@ -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;

View File

@@ -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`);

View File

@@ -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);

View File

@@ -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<HighGuid::Player>(fields[14].GetUInt64()));
SetClass(fields[8].GetUInt8());
SetSex(fields[9].GetUInt8());
SetFlags(fields[10].GetUInt8());
SetCorpseDynamicFlags(CorpseDynFlags(fields[11].GetUInt8()));
SetOwnerGUID(ObjectGuid::Create<HighGuid::Player>(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);

View File

@@ -83,6 +83,7 @@ class TC_GAME_API Corpse : public WorldObject, public GridObject<Corpse>
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); }

View File

@@ -4483,9 +4483,9 @@ void CorpseData::WriteCreate(ByteBuffer& data, EnumFlag<UpdateFieldFlag> 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);

View File

@@ -837,9 +837,9 @@ struct CorpseData : public IsUpdateFieldStructureTag, public HasChangesMask<33>
UpdateField<ObjectGuid, 0, 4> PartyGUID;
UpdateField<ObjectGuid, 0, 5> GuildGUID;
UpdateField<uint32, 0, 6> DisplayID;
UpdateField<uint8, 0, 7> Unused;
UpdateField<uint8, 0, 8> RaceID;
UpdateField<uint8, 0, 9> Sex;
UpdateField<uint8, 0, 7> RaceID;
UpdateField<uint8, 0, 8> Sex;
UpdateField<uint8, 0, 9> Class;
UpdateField<uint32, 0, 10> Flags;
UpdateField<int32, 0, 11> FactionTemplate;
UpdateField<uint32, 0, 12> StateSpellVisualKitID;

View File

@@ -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());

View File

@@ -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());