feat(Core/Misc): implement ObjectGuid class (port from TC) (#4885)

This commit is contained in:
UltraNix
2021-04-25 22:18:03 +02:00
committed by GitHub
parent 91081f4ad8
commit f4c226423d
568 changed files with 10655 additions and 11019 deletions

View File

@@ -43,9 +43,9 @@ u_map_magic MapLiquidMagic = { {'M', 'L', 'I', 'Q'} };
Map::~Map()
{
sScriptMgr->OnDestroyMap(this);
// UnloadAll must be called before deleting the map
UnloadAll();
sScriptMgr->OnDestroyMap(this);
while (!i_worldObjects.empty())
{
@@ -300,6 +300,25 @@ void Map::AddToGrid(DynamicObject* obj, Cell const& cell)
obj->SetCurrentCell(cell);
}
template<>
void Map::AddToGrid(Corpse* obj, Cell const& cell)
{
NGridType* grid = getNGrid(cell.GridX(), cell.GridY());
// Corpses are a special object type - they can be added to grid via a call to AddToMap
// or loaded through ObjectGridLoader.
// Both corpses loaded from database and these freshly generated by Player::CreateCoprse are added to _corpsesByCell
// ObjectGridLoader loads all corpses from _corpsesByCell even if they were already added to grid before it was loaded
// so we need to explicitly check it here (Map::AddToGrid is only called from Player::BuildPlayerRepop, not from ObjectGridLoader)
// to avoid failing an assertion in GridObject::AddToGrid
if (grid->isGridObjectDataLoaded())
{
if (obj->IsWorldObject())
grid->GetGridType(cell.CellX(), cell.CellY()).AddWorldObject(obj);
else
grid->GetGridType(cell.CellX(), cell.CellY()).AddGridObject(obj);
}
}
template<class T>
void Map::SwitchGridContainers(T* /*obj*/, bool /*on*/)
{
@@ -312,7 +331,8 @@ void Map::SwitchGridContainers(Creature* obj, bool on)
CellCoord p = acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
if (!p.IsCoordValid())
{
LOG_ERROR("server", "Map::SwitchGridContainers: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
LOG_ERROR("server", "Map::SwitchGridContainers: Object %s has invalid coordinates X:%f Y:%f grid cell [%u:%u]",
obj->GetGUID().ToString().c_str(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
return;
}
@@ -321,7 +341,7 @@ void Map::SwitchGridContainers(Creature* obj, bool on)
return;
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("maps", "Switch object " SZFMTD " from grid[%u, %u] %d", obj->GetGUID(), cell.GridX(), cell.GridY(), on);
LOG_DEBUG("maps", "Switch object %s from grid[%u, %u] %d", obj->GetGUID().ToString().c_str(), cell.GridX(), cell.GridY(), on);
#endif
NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY());
ASSERT(ngrid != nullptr);
@@ -351,7 +371,8 @@ void Map::SwitchGridContainers(GameObject* obj, bool on)
CellCoord p = acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
if (!p.IsCoordValid())
{
LOG_ERROR("server", "Map::SwitchGridContainers: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
LOG_ERROR("server", "Map::SwitchGridContainers: Object %s has invalid coordinates X:%f Y:%f grid cell [%u:%u]",
obj->GetGUID().ToString().c_str(), obj->GetPositionX(), obj->GetPositionY(), p.x_coord, p.y_coord);
return;
}
@@ -359,7 +380,7 @@ void Map::SwitchGridContainers(GameObject* obj, bool on)
if (!IsGridLoaded(GridCoord(cell.data.Part.grid_x, cell.data.Part.grid_y)))
return;
//TC_LOG_DEBUG(LOG_FILTER_MAPS, "Switch object " UI64FMTD " from grid[%u, %u] %u", obj->GetGUID(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
//TC_LOG_DEBUG(LOG_FILTER_MAPS, "Switch object %s from grid[%u, %u] %u", obj->GetGUID().ToString().c_str(), cell.data.Part.grid_x, cell.data.Part.grid_y, on);
NGridType* ngrid = getNGrid(cell.GridX(), cell.GridY());
ASSERT(ngrid != nullptr);
@@ -389,14 +410,9 @@ void Map::DeleteFromWorld(T* obj)
template<>
void Map::DeleteFromWorld(Player* player)
{
sObjectAccessor->RemoveObject(player);
ObjectAccessor::RemoveObject(player);
// pussywizard: optimization
std::string charName = player->GetName();
std::transform(charName.begin(), charName.end(), charName.begin(), ::tolower);
sObjectAccessor->playerNameToPlayerPointer.erase(charName);
sObjectAccessor->RemoveUpdateObject(player); //TODO: I do not know why we need this, it should be removed in ~Object anyway
RemoveUpdateObject(player); //TODO: I do not know why we need this, it should be removed in ~Object anyway
delete player;
}
@@ -454,8 +470,6 @@ bool Map::EnsureGridLoaded(const Cell& cell)
ObjectGridLoader loader(*grid, this, cell);
loader.LoadN();
// Add resurrectable corpses to world object list in grid
sObjectAccessor->AddCorpsesToGrid(GridCoord(cell.GridX(), cell.GridY()), grid->GetGridType(cell.CellX(), cell.CellY()), this);
Balance();
return true;
//}
@@ -481,7 +495,8 @@ bool Map::AddPlayerToMap(Player* player)
CellCoord cellCoord = acore::ComputeCellCoord(player->GetPositionX(), player->GetPositionY());
if (!cellCoord.IsCoordValid())
{
LOG_ERROR("server", "Map::Add: Player (GUID: %u) has invalid coordinates X:%f Y:%f grid cell [%u:%u]", player->GetGUIDLow(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
LOG_ERROR("server", "Map::Add: Player (%s) has invalid coordinates X:%f Y:%f grid cell [%u:%u]",
player->GetGUID().ToString().c_str(), player->GetPositionX(), player->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
return false;
}
@@ -501,6 +516,9 @@ bool Map::AddPlayerToMap(Player* player)
player->m_clientGUIDs.clear();
player->UpdateObjectVisibility(false);
if (player->IsAlive())
ConvertCorpseToBones(player->GetGUID());
sScriptMgr->OnPlayerEnterMap(this, player);
return true;
}
@@ -540,7 +558,8 @@ bool Map::AddToMap(T* obj, bool checkTransport)
ASSERT(cellCoord.IsCoordValid());
if (!cellCoord.IsCoordValid())
{
LOG_ERROR("server", "Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
LOG_ERROR("server", "Map::Add: Object %s has invalid coordinates X:%f Y:%f grid cell [%u:%u]",
obj->GetGUID().ToString().c_str(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
return false; //Should delete object
}
@@ -588,7 +607,8 @@ bool Map::AddToMap(MotionTransport* obj, bool /*checkTransport*/)
CellCoord cellCoord = acore::ComputeCellCoord(obj->GetPositionX(), obj->GetPositionY());
if (!cellCoord.IsCoordValid())
{
LOG_ERROR("server", "Map::Add: Object " UI64FMTD " has invalid coordinates X:%f Y:%f grid cell [%u:%u]", obj->GetGUID(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
LOG_ERROR("server", "Map::Add: Object %s has invalid coordinates X:%f Y:%f grid cell [%u:%u]",
obj->GetGUID().ToString().c_str(), obj->GetPositionX(), obj->GetPositionY(), cellCoord.x_coord, cellCoord.y_coord);
return false; //Should delete object
}
@@ -830,6 +850,8 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
transport->Update(t_diff);
}
SendObjectUpdates();
///- Process necessary scripts
if (!m_scriptSchedule.empty())
{
@@ -845,8 +867,6 @@ void Map::Update(const uint32 t_diff, const uint32 s_diff, bool /*thread*/)
HandleDelayedVisibility();
sScriptMgr->OnMapUpdate(this, t_diff);
BuildAndSendUpdateForObjects(); // pussywizard
}
void Map::HandleDelayedVisibility()
@@ -1263,6 +1283,20 @@ void Map::UnloadAll()
}
_transports.clear();
for (auto& cellCorpsePair : _corpsesByCell)
{
for (Corpse* corpse : cellCorpsePair.second)
{
corpse->RemoveFromWorld();
corpse->ResetMap();
delete corpse;
}
}
_corpsesByCell.clear();
_corpsesByPlayer.clear();
_corpseBones.clear();
}
// *****************************
@@ -2333,7 +2367,7 @@ void Map::UpdateObjectsVisibilityFor(Player* player, Cell cell, CellCoord cellpa
void Map::SendInitSelf(Player* player)
{
#if defined(ENABLE_EXTRAS) && defined(ENABLE_EXTRA_LOGS)
LOG_DEBUG("server", "Creating player data for himself %u", player->GetGUIDLow());
LOG_DEBUG("server", "Creating player data for himself %s", player->GetGUID().ToString().c_str());
#endif
UpdateData data;
@@ -2378,9 +2412,9 @@ void Map::SendRemoveTransports(Player* player)
(*itr)->BuildOutOfRangeUpdateBlock(&transData);
// pussywizard: remove static transports from client
for (Player::ClientGUIDs::const_iterator it = player->m_clientGUIDs.begin(); it != player->m_clientGUIDs.end(); )
for (GuidUnorderedSet::const_iterator it = player->m_clientGUIDs.begin(); it != player->m_clientGUIDs.end(); )
{
if (IS_TRANSPORT_GUID(*it))
if ((*it).IsTransport())
{
transData.AddOutOfRangeGUID(*it);
it = player->m_clientGUIDs.erase(it);
@@ -2404,6 +2438,29 @@ inline void Map::setNGrid(NGridType* grid, uint32 x, uint32 y)
i_grids[x][y] = grid;
}
void Map::SendObjectUpdates()
{
UpdateDataMapType update_players;
UpdatePlayerSet player_set;
while (!_updateObjects.empty())
{
Object* obj = *_updateObjects.begin();
ASSERT(obj->IsInWorld());
_updateObjects.erase(_updateObjects.begin());
obj->BuildUpdate(update_players, player_set);
}
WorldPacket packet; // here we allocate a std::vector with a size of 0x10000
for (UpdateDataMapType::iterator iter = update_players.begin(); iter != update_players.end(); ++iter)
{
iter->second.BuildPacket(&packet);
iter->first->GetSession()->SendPacket(&packet);
packet.clear(); // clean the string
}
}
void Map::DelayedUpdate(const uint32 t_diff)
{
for (_transportsUpdateIter = _transports.begin(); _transportsUpdateIter != _transports.end();)
@@ -2427,7 +2484,7 @@ void Map::AddObjectToRemoveList(WorldObject* obj)
obj->CleanupsBeforeDelete(false); // remove or simplify at least cross referenced links
i_objectsToRemove.insert(obj);
//LOG_DEBUG("maps", "Object (GUID: %u TypeId: %u) added to removing list.", obj->GetGUIDLow(), obj->GetTypeId());
//LOG_DEBUG("maps", "Object (%s) added to removing list.", obj->GetGUID().ToString().c_str());
}
void Map::AddObjectToSwitchList(WorldObject* obj, bool on)
@@ -2485,7 +2542,7 @@ void Map::RemoveAllObjectsInRemoveList()
{
Corpse* corpse = ObjectAccessor::GetCorpse(*obj, obj->GetGUID());
if (!corpse)
LOG_ERROR("server", "Tried to delete corpse/bones %u that is not in map.", obj->GetGUIDLow());
LOG_ERROR("server", "Tried to delete corpse/bones %s that is not in map.", obj->GetGUID().ToString().c_str());
else
RemoveFromMap(corpse, true);
break;
@@ -2651,7 +2708,8 @@ bool InstanceMap::CanEnter(Player* player, bool loginCheck)
{
if (!loginCheck && player->GetMapRef().getTarget() == this)
{
LOG_ERROR("server", "InstanceMap::CanEnter - player %s(%u) already in map %d, %d, %d!", player->GetName().c_str(), player->GetGUIDLow(), GetId(), GetInstanceId(), GetSpawnMode());
LOG_ERROR("server", "InstanceMap::CanEnter - player %s (%s) already in map %d, %d, %d!",
player->GetName().c_str(), player->GetGUID().ToString().c_str(), GetId(), GetInstanceId(), GetSpawnMode());
ABORT();
return false;
}
@@ -2736,25 +2794,27 @@ bool InstanceMap::AddPlayerToMap(Player* player)
}
// check for existing instance binds
InstancePlayerBind* playerBind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUIDLow(), GetId(), Difficulty(GetSpawnMode()));
InstancePlayerBind* playerBind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUID(), GetId(), Difficulty(GetSpawnMode()));
if (playerBind && playerBind->perm)
{
if (playerBind->save != mapSave)
{
LOG_ERROR("server", "InstanceMap::Add: player %s(%d) is permanently bound to instance %d, %d, %d, %d but he is being put into instance %d, %d, %d, %d", player->GetName().c_str(), player->GetGUIDLow(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(), playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->CanReset());
LOG_ERROR("server", "InstanceMap::Add: player %s (%s) is permanently bound to instance %d, %d, %d, %d but he is being put into instance %d, %d, %d, %d",
player->GetName().c_str(), player->GetGUID().ToString().c_str(), playerBind->save->GetMapId(), playerBind->save->GetInstanceId(), playerBind->save->GetDifficulty(),
playerBind->save->CanReset(), mapSave->GetMapId(), mapSave->GetInstanceId(), mapSave->GetDifficulty(), mapSave->CanReset());
return false;
}
}
else
{
playerBind = sInstanceSaveMgr->PlayerBindToInstance(player->GetGUIDLow(), mapSave, false, player);
playerBind = sInstanceSaveMgr->PlayerBindToInstance(player->GetGUID(), mapSave, false, player);
// pussywizard: bind lider also if not yet bound
if (Group* g = player->GetGroup())
if (g->GetLeaderGUID() != player->GetGUID())
if (!sInstanceSaveMgr->PlayerGetBoundInstance(GUID_LOPART(g->GetLeaderGUID()), mapSave->GetMapId(), mapSave->GetDifficulty()))
if (!sInstanceSaveMgr->PlayerGetBoundInstance(g->GetLeaderGUID(), mapSave->GetMapId(), mapSave->GetDifficulty()))
{
sInstanceSaveMgr->PlayerCreateBoundInstancesMaps(GUID_LOPART(g->GetLeaderGUID()));
sInstanceSaveMgr->PlayerBindToInstance(GUID_LOPART(g->GetLeaderGUID()), mapSave, false, ObjectAccessor::FindPlayerInOrOutOfWorld(g->GetLeaderGUID()));
sInstanceSaveMgr->PlayerCreateBoundInstancesMaps(g->GetLeaderGUID());
sInstanceSaveMgr->PlayerBindToInstance(g->GetLeaderGUID(), mapSave, false, ObjectAccessor::FindConnectedPlayer(g->GetLeaderGUID()));
}
}
@@ -2857,7 +2917,7 @@ void InstanceMap::CreateInstanceScript(bool load, std::string data, uint32 compl
/*
Returns true if there are no players in the instance
*/
bool InstanceMap::Reset(uint8 method, std::list<uint32>* globalResetSkipList)
bool InstanceMap::Reset(uint8 method, GuidList* globalResetSkipList)
{
if (method == INSTANCE_RESET_GLOBAL)
{
@@ -2865,7 +2925,7 @@ bool InstanceMap::Reset(uint8 method, std::list<uint32>* globalResetSkipList)
for (MapRefManager::iterator itr = m_mapRefManager.begin(); itr != m_mapRefManager.end(); ++itr)
{
// teleport players that are no longer bound (can be still bound if extended id)
if (!globalResetSkipList || std::find(globalResetSkipList->begin(), globalResetSkipList->end(), itr->GetSource()->GetGUIDLow()) == globalResetSkipList->end())
if (!globalResetSkipList || std::find(globalResetSkipList->begin(), globalResetSkipList->end(), itr->GetSource()->GetGUID()) == globalResetSkipList->end())
itr->GetSource()->RepopAtGraveyard();
}
@@ -2926,14 +2986,14 @@ void InstanceMap::PermBindAllPlayers()
// players inside an instance cannot be bound to other instances
// some players may already be permanently bound, in this case nothing happens
InstancePlayerBind* bind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUIDLow(), save->GetMapId(), save->GetDifficulty());
InstancePlayerBind* bind = sInstanceSaveMgr->PlayerGetBoundInstance(player->GetGUID(), save->GetMapId(), save->GetDifficulty());
if (!bind || !bind->perm)
{
WorldPacket data(SMSG_INSTANCE_SAVE_CREATED, 4);
data << uint32(0);
player->GetSession()->SendPacket(&data);
sInstanceSaveMgr->PlayerBindToInstance(player->GetGUIDLow(), save, true, player);
sInstanceSaveMgr->PlayerBindToInstance(player->GetGUID(), save, true, player);
}
// Xinef: Difficulty change prevention
@@ -2947,7 +3007,10 @@ void InstanceMap::UnloadAll()
ASSERT(!HavePlayers());
if (m_resetAfterUnload == true)
{
DeleteRespawnTimes();
DeleteCorpseData();
}
Map::UnloadAll();
}
@@ -3010,7 +3073,7 @@ bool BattlegroundMap::CanEnter(Player* player, bool loginCheck)
{
if (!loginCheck && player->GetMapRef().getTarget() == this)
{
LOG_ERROR("server", "BGMap::CanEnter - player %u is already in map!", player->GetGUIDLow());
LOG_ERROR("server", "BGMap::CanEnter - player %s is already in map!", player->GetGUID().ToString().c_str());
ABORT();
return false;
}
@@ -3058,43 +3121,38 @@ void BattlegroundMap::RemoveAllPlayers()
player->TeleportTo(player->GetEntryPoint());
}
Player* Map::GetPlayer(uint64 guid)
Corpse* Map::GetCorpse(ObjectGuid const guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (Player*)nullptr);
return _objectsStore.Find<Corpse>(guid);
}
Creature* Map::GetCreature(uint64 guid)
Creature* Map::GetCreature(ObjectGuid const guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (Creature*)nullptr);
return _objectsStore.Find<Creature>(guid);
}
GameObject* Map::GetGameObject(uint64 guid)
GameObject* Map::GetGameObject(ObjectGuid const guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (GameObject*)nullptr);
return _objectsStore.Find<GameObject>(guid);
}
Transport* Map::GetTransport(uint64 guid)
Pet* Map::GetPet(ObjectGuid const guid)
{
if (GUID_HIPART(guid) != HIGHGUID_MO_TRANSPORT && GUID_HIPART(guid) != HIGHGUID_TRANSPORT)
return _objectsStore.Find<Pet>(guid);
}
Transport* Map::GetTransport(ObjectGuid guid)
{
if (guid.GetHigh() != HighGuid::Mo_Transport && guid.GetHigh() != HighGuid::Transport)
return nullptr;
GameObject* go = GetGameObject(guid);
return go ? go->ToTransport() : nullptr;
}
DynamicObject* Map::GetDynamicObject(uint64 guid)
DynamicObject* Map::GetDynamicObject(ObjectGuid guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (DynamicObject*)nullptr);
}
Pet* Map::GetPet(uint64 guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (Pet*)nullptr);
}
Corpse* Map::GetCorpse(uint64 guid)
{
return ObjectAccessor::GetObjectInMap(guid, this, (Corpse*)nullptr);
return _objectsStore.Find<DynamicObject>(guid);
}
void Map::UpdateIteratorBack(Player* player)
@@ -3103,12 +3161,12 @@ void Map::UpdateIteratorBack(Player* player)
m_mapRefIter = m_mapRefIter->nocheck_prev();
}
void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t& respawnTime)
void Map::SaveCreatureRespawnTime(ObjectGuid::LowType spawnId, time_t& respawnTime)
{
if (!respawnTime)
{
// Delete only
RemoveCreatureRespawnTime(dbGuid);
RemoveCreatureRespawnTime(spawnId);
return;
}
@@ -3116,33 +3174,33 @@ void Map::SaveCreatureRespawnTime(uint32 dbGuid, time_t& respawnTime)
if (GetInstanceResetPeriod() > 0 && respawnTime - now + 5 >= GetInstanceResetPeriod())
respawnTime = now + YEAR;
_creatureRespawnTimes[dbGuid] = respawnTime;
_creatureRespawnTimes[spawnId] = respawnTime;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_CREATURE_RESPAWN);
stmt->setUInt32(0, dbGuid);
stmt->setUInt32(0, spawnId);
stmt->setUInt32(1, uint32(respawnTime));
stmt->setUInt16(2, GetId());
stmt->setUInt32(3, GetInstanceId());
CharacterDatabase.Execute(stmt);
}
void Map::RemoveCreatureRespawnTime(uint32 dbGuid)
void Map::RemoveCreatureRespawnTime(ObjectGuid::LowType spawnId)
{
_creatureRespawnTimes.erase(dbGuid);
_creatureRespawnTimes.erase(spawnId);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CREATURE_RESPAWN);
stmt->setUInt32(0, dbGuid);
stmt->setUInt32(0, spawnId);
stmt->setUInt16(1, GetId());
stmt->setUInt32(2, GetInstanceId());
CharacterDatabase.Execute(stmt);
}
void Map::SaveGORespawnTime(uint32 dbGuid, time_t& respawnTime)
void Map::SaveGORespawnTime(ObjectGuid::LowType spawnId, time_t& respawnTime)
{
if (!respawnTime)
{
// Delete only
RemoveGORespawnTime(dbGuid);
RemoveGORespawnTime(spawnId);
return;
}
@@ -3150,22 +3208,22 @@ void Map::SaveGORespawnTime(uint32 dbGuid, time_t& respawnTime)
if (GetInstanceResetPeriod() > 0 && respawnTime - now + 5 >= GetInstanceResetPeriod())
respawnTime = now + YEAR;
_goRespawnTimes[dbGuid] = respawnTime;
_goRespawnTimes[spawnId] = respawnTime;
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_REP_GO_RESPAWN);
stmt->setUInt32(0, dbGuid);
stmt->setUInt32(0, spawnId);
stmt->setUInt32(1, uint32(respawnTime));
stmt->setUInt16(2, GetId());
stmt->setUInt32(3, GetInstanceId());
CharacterDatabase.Execute(stmt);
}
void Map::RemoveGORespawnTime(uint32 dbGuid)
void Map::RemoveGORespawnTime(ObjectGuid::LowType spawnId)
{
_goRespawnTimes.erase(dbGuid);
_goRespawnTimes.erase(spawnId);
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_GO_RESPAWN);
stmt->setUInt32(0, dbGuid);
stmt->setUInt32(0, spawnId);
stmt->setUInt16(1, GetId());
stmt->setUInt32(2, GetInstanceId());
CharacterDatabase.Execute(stmt);
@@ -3181,10 +3239,10 @@ void Map::LoadRespawnTimes()
do
{
Field* fields = result->Fetch();
uint32 loguid = fields[0].GetUInt32();
ObjectGuid::LowType lowguid = fields[0].GetUInt32();
uint32 respawnTime = fields[1].GetUInt32();
_creatureRespawnTimes[loguid] = time_t(respawnTime);
_creatureRespawnTimes[lowguid] = time_t(respawnTime);
} while (result->NextRow());
}
@@ -3196,10 +3254,10 @@ void Map::LoadRespawnTimes()
do
{
Field* fields = result->Fetch();
uint32 loguid = fields[0].GetUInt32();
ObjectGuid::LowType lowguid = fields[0].GetUInt32();
uint32 respawnTime = fields[1].GetUInt32();
_goRespawnTimes[loguid] = time_t(respawnTime);
_goRespawnTimes[lowguid] = time_t(respawnTime);
} while (result->NextRow());
}
}
@@ -3299,7 +3357,8 @@ void Map::LogEncounterFinished(EncounterCreditType type, uint32 creditEntry)
auraStr += buffer2;
}
snprintf(buffer, 16384, "%s (guid: %u, acc: %u, ip: %s, guild: %u), xyz: (%.1f, %.1f, %.1f), auras: %s\n", p->GetName().c_str(), p->GetGUIDLow(), p->GetSession()->GetAccountId(), p->GetSession()->GetRemoteAddress().c_str(), p->GetGuildId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), auraStr.c_str());
snprintf(buffer, 16384, "%s (%s, acc: %u, ip: %s, guild: %u), xyz: (%.1f, %.1f, %.1f), auras: %s\n",
p->GetName().c_str(), p->GetGUID().ToString().c_str(), p->GetSession()->GetAccountId(), p->GetSession()->GetRemoteAddress().c_str(), p->GetGuildId(), p->GetPositionX(), p->GetPositionY(), p->GetPositionZ(), auraStr.c_str());
playersInfo += buffer;
}
CleanStringForMysqlQuery(playersInfo);
@@ -3322,15 +3381,15 @@ void Map::AllTransportsRemovePassengers()
(*itr)->RemovePassenger(*((*itr)->GetPassengers().begin()), true);
}
time_t Map::GetLinkedRespawnTime(uint64 guid) const
time_t Map::GetLinkedRespawnTime(ObjectGuid guid) const
{
uint64 linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid);
switch (GUID_HIPART(linkedGuid))
ObjectGuid linkedGuid = sObjectMgr->GetLinkedRespawnGuid(guid);
switch (linkedGuid.GetHigh())
{
case HIGHGUID_UNIT:
return GetCreatureRespawnTime(GUID_LOPART(linkedGuid));
case HIGHGUID_GAMEOBJECT:
return GetGORespawnTime(GUID_LOPART(linkedGuid));
case HighGuid::Unit:
return GetCreatureRespawnTime(linkedGuid.GetCounter());
case HighGuid::GameObject:
return GetGORespawnTime(linkedGuid.GetCounter());
default:
break;
}
@@ -3338,6 +3397,114 @@ time_t Map::GetLinkedRespawnTime(uint64 guid) const
return time_t(0);
}
void Map::AddCorpse(Corpse* corpse)
{
corpse->SetMap(this);
_corpsesByCell[corpse->GetCellCoord().GetId()].insert(corpse);
if (corpse->GetType() != CORPSE_BONES)
_corpsesByPlayer[corpse->GetOwnerGUID()] = corpse;
else
_corpseBones.insert(corpse);
}
void Map::RemoveCorpse(Corpse* corpse)
{
ASSERT(corpse);
corpse->DestroyForNearbyPlayers();
if (corpse->IsInGrid())
RemoveFromMap(corpse, false);
else
{
corpse->RemoveFromWorld();
corpse->ResetMap();
}
_corpsesByCell[corpse->GetCellCoord().GetId()].erase(corpse);
if (corpse->GetType() != CORPSE_BONES)
_corpsesByPlayer.erase(corpse->GetOwnerGUID());
else
_corpseBones.erase(corpse);
}
Corpse* Map::ConvertCorpseToBones(ObjectGuid const ownerGuid, bool insignia /*= false*/)
{
Corpse* corpse = GetCorpseByPlayer(ownerGuid);
if (!corpse)
return nullptr;
RemoveCorpse(corpse);
// remove corpse from DB
SQLTransaction trans = CharacterDatabase.BeginTransaction();
corpse->DeleteFromDB(trans);
CharacterDatabase.CommitTransaction(trans);
Corpse* bones = NULL;
// create the bones only if the map and the grid is loaded at the corpse's location
// ignore bones creating option in case insignia
if ((insignia ||
(IsBattlegroundOrArena() ? sWorld->getBoolConfig(CONFIG_DEATH_BONES_BG_OR_ARENA) : sWorld->getBoolConfig(CONFIG_DEATH_BONES_WORLD))) &&
!IsRemovalGrid(corpse->GetPositionX(), corpse->GetPositionY()))
{
// Create bones, don't change Corpse
bones = new Corpse();
bones->Create(corpse->GetGUID().GetCounter());
for (uint8 i = OBJECT_FIELD_TYPE + 1; i < CORPSE_END; ++i) // don't overwrite guid and object type
bones->SetUInt32Value(i, corpse->GetUInt32Value(i));
bones->SetCellCoord(corpse->GetCellCoord());
bones->Relocate(corpse->GetPositionX(), corpse->GetPositionY(), corpse->GetPositionZ(), corpse->GetOrientation());
bones->SetPhaseMask(corpse->GetPhaseMask(), false);
bones->SetUInt32Value(CORPSE_FIELD_FLAGS, CORPSE_FLAG_UNK2 | CORPSE_FLAG_BONES);
bones->SetGuidValue(CORPSE_FIELD_OWNER, ObjectGuid::Empty);
for (uint8 i = 0; i < EQUIPMENT_SLOT_END; ++i)
if (corpse->GetUInt32Value(CORPSE_FIELD_ITEM + i))
bones->SetUInt32Value(CORPSE_FIELD_ITEM + i, 0);
AddCorpse(bones);
// add bones in grid store if grid loaded where corpse placed
AddToMap(bones);
}
// all references to the corpse should be removed at this point
delete corpse;
return bones;
}
void Map::RemoveOldCorpses()
{
time_t now = time(nullptr);
std::vector<ObjectGuid> corpses;
corpses.reserve(_corpsesByPlayer.size());
for (auto const& p : _corpsesByPlayer)
if (p.second->IsExpired(now))
corpses.push_back(p.first);
for (ObjectGuid const& ownerGuid : corpses)
ConvertCorpseToBones(ownerGuid);
std::vector<Corpse*> expiredBones;
for (Corpse* bones : _corpseBones)
if (bones->IsExpired(now))
expiredBones.push_back(bones);
for (Corpse* bones : expiredBones)
{
RemoveCorpse(bones);
delete bones;
}
}
void Map::SendZoneDynamicInfo(Player* player)
{
uint32 zoneId = GetZoneId(player->GetPositionX(), player->GetPositionY(), player->GetPositionZ());
@@ -3630,3 +3797,47 @@ bool Map::CheckCollisionAndGetValidCoords(const WorldObject* source, float start
return failOnCollision ? !collided : true;
}
void Map::LoadCorpseData()
{
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CORPSES);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, GetInstanceId());
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// SELECT posX, posY, posZ, orientation, mapId, displayId, itemCache, bytes1, bytes2, guildId, flags, dynFlags, time, corpseType, instanceId, phaseMask, guid FROM corpse WHERE mapId = ? AND instanceId = ?
PreparedQueryResult result = CharacterDatabase.Query(stmt);
if (!result)
return;
do
{
Field* fields = result->Fetch();
CorpseType type = CorpseType(fields[13].GetUInt8());
uint32 guid = fields[16].GetUInt32();
if (type >= MAX_CORPSE_TYPE || type == CORPSE_BONES)
{
LOG_ERROR("server", "Corpse (guid: %u) have wrong corpse type (%u), not loading.", guid, type);
continue;
}
Corpse* corpse = new Corpse(type);
if (!corpse->LoadCorpseFromDB(GenerateLowGuid<HighGuid::Corpse>(), fields))
{
delete corpse;
continue;
}
AddCorpse(corpse);
} while (result->NextRow());
}
void Map::DeleteCorpseData()
{
// DELETE FROM corpse WHERE mapId = ? AND instanceId = ?
PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_DEL_CORPSES_FROM_MAP);
stmt->setUInt32(0, GetId());
stmt->setUInt32(1, GetInstanceId());
CharacterDatabase.Execute(stmt);
}