fix(Core/GameObjects): Gameobject rotation and moving actions not updating to client (#5223)

This commit is contained in:
UltraNix
2021-05-03 03:25:50 +02:00
committed by GitHub
parent 8e0bffa80b
commit 87a35b6569
5 changed files with 57 additions and 18 deletions

View File

@@ -80,6 +80,7 @@ void WorldDatabaseConnection::DoPrepareStatements()
PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_DEL_DISABLES, "DELETE FROM disables WHERE entry = ? AND sourceType = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA, "UPDATE creature SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_UPD_CREATURE_ZONE_AREA_DATA, "UPDATE creature SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC); PrepareStatement(WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, "UPDATE gameobject SET zoneId = ?, areaId = ? WHERE guid = ?", CONNECTION_ASYNC);
PrepareStatement(WORLD_INS_GAMEOBJECT_ADDON, "INSERT INTO gameobject_addon (guid, invisibilityType, invisibilityValue) VALUES (?, 0, 0)", CONNECTION_ASYNC);
// 0: uint8 // 0: uint8
PrepareStatement(WORLD_SEL_REQ_XP, "SELECT Experience FROM player_xp_for_level WHERE Level = ?", CONNECTION_SYNCH); PrepareStatement(WORLD_SEL_REQ_XP, "SELECT Experience FROM player_xp_for_level WHERE Level = ?", CONNECTION_SYNCH);
} }

View File

@@ -102,6 +102,7 @@ enum WorldDatabaseStatements
WORLD_UPD_CREATURE_ZONE_AREA_DATA, WORLD_UPD_CREATURE_ZONE_AREA_DATA,
WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA, WORLD_UPD_GAMEOBJECT_ZONE_AREA_DATA,
WORLD_SEL_REQ_XP, WORLD_SEL_REQ_XP,
WORLD_INS_GAMEOBJECT_ADDON,
MAX_WORLDDATABASE_STATEMENTS MAX_WORLDDATABASE_STATEMENTS
}; };

View File

@@ -845,7 +845,7 @@ void GameObject::getFishLootJunk(Loot* fishloot, Player* loot_owner)
} }
} }
void GameObject::SaveToDB() void GameObject::SaveToDB(bool saveAddon /*= false*/)
{ {
// this should only be used when the gameobject has already been loaded // this should only be used when the gameobject has already been loaded
// preferably after adding to map, because mapid may not be valid otherwise // preferably after adding to map, because mapid may not be valid otherwise
@@ -856,10 +856,10 @@ void GameObject::SaveToDB()
return; return;
} }
SaveToDB(GetMapId(), data->spawnMask, data->phaseMask); SaveToDB(GetMapId(), data->spawnMask, data->phaseMask, saveAddon);
} }
void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask) void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool saveAddon /*= false*/)
{ {
const GameObjectTemplate* goI = GetGOInfo(); const GameObjectTemplate* goI = GetGOInfo();
@@ -914,6 +914,14 @@ void GameObject::SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask)
stmt->setUInt8(index++, uint8(GetGoState())); stmt->setUInt8(index++, uint8(GetGoState()));
trans->Append(stmt); trans->Append(stmt);
if (saveAddon && !sObjectMgr->GetGameObjectAddon(m_spawnId))
{
index = 0;
stmt = WorldDatabase.GetPreparedStatement(WORLD_INS_GAMEOBJECT_ADDON);
stmt->setUInt32(index++, m_spawnId);
trans->Append(stmt);
}
WorldDatabase.CommitTransaction(trans); WorldDatabase.CommitTransaction(trans);
} }

View File

@@ -759,8 +759,8 @@ public:
// overwrite WorldObject function for proper name localization // overwrite WorldObject function for proper name localization
[[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override; [[nodiscard]] std::string const& GetNameForLocaleIdx(LocaleConstant locale_idx) const override;
void SaveToDB(); void SaveToDB(bool saveAddon = false);
void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask); void SaveToDB(uint32 mapid, uint8 spawnMask, uint32 phaseMask, bool saveAddon = false);
bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); } bool LoadFromDB(ObjectGuid::LowType guid, Map* map) { return LoadGameObjectFromDB(guid, map, false); }
bool LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true); bool LoadGameObjectFromDB(ObjectGuid::LowType guid, Map* map, bool addToMap = true);
void DeleteFromDB(); void DeleteFromDB();

View File

@@ -402,12 +402,25 @@ public:
oz = player->GetOrientation(); oz = player->GetOrientation();
} }
object->SetWorldRotationAngles(oz, oy, ox); Map* map = object->GetMap();
object->DestroyForNearbyPlayers();
object->UpdateObjectVisibility();
object->SaveToDB(); object->Relocate(object->GetPositionX(), object->GetPositionY(), object->GetPositionZ(), oz);
object->Refresh(); object->SetWorldRotationAngles(oz, oy, ox);
object->SaveToDB(true);
// Generate a completely new spawn with new guid
// 3.3.5a client caches recently deleted objects and brings them back to life
// when CreateObject block for this guid is received again
// however it entirely skips parsing that block and only uses already known location
object->Delete();
object = new GameObject();
if (!object->LoadGameObjectFromDB(guidLow, map))
{
delete object;
return false;
}
handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId(), oz, oy, ox); handler->PSendSysMessage(LANG_COMMAND_TURNOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId(), oz, oy, ox);
@@ -438,12 +451,10 @@ public:
char* toY = strtok(nullptr, " "); char* toY = strtok(nullptr, " ");
char* toZ = strtok(nullptr, " "); char* toZ = strtok(nullptr, " ");
Position pos;
if (!toX) if (!toX)
{ {
Player* player = handler->GetSession()->GetPlayer(); pos = handler->GetSession()->GetPlayer()->GetPosition();
object->GetMap()->GameObjectRelocation(object, player->GetPositionX(), player->GetPositionY(), player->GetPositionZ(), object->GetOrientation());
object->DestroyForNearbyPlayers();
object->UpdateObjectVisibility();
} }
else else
{ {
@@ -461,13 +472,31 @@ public:
return false; return false;
} }
object->GetMap()->GameObjectRelocation(object, x, y, z, object->GetOrientation()); pos.Relocate(x, y, z);
object->DestroyForNearbyPlayers();
object->UpdateObjectVisibility();
} }
Map* map = object->GetMap();
pos.SetOrientation(object->GetOrientation());
object->Relocate(pos);
// update which cell has this gameobject registered for loading
sObjectMgr->RemoveGameobjectFromGrid(guidLow, object->GetGOData());
object->SaveToDB(); object->SaveToDB();
object->Refresh(); sObjectMgr->AddGameobjectToGrid(guidLow, object->GetGOData());
// Generate a completely new spawn with new guid
// 3.3.5a client caches recently deleted objects and brings them back to life
// when CreateObject block for this guid is received again
// however it entirely skips parsing that block and only uses already known location
object->Delete();
object = new GameObject();
if (!object->LoadGameObjectFromDB(guidLow, map))
{
delete object;
return false;
}
handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId()); handler->PSendSysMessage(LANG_COMMAND_MOVEOBJMESSAGE, object->GetSpawnId(), object->GetGOInfo()->name.c_str(), object->GetSpawnId());