aboutsummaryrefslogtreecommitdiff
path: root/src/server/game/Maps/Map.cpp
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2020-02-08 20:22:37 +0100
committerShauren <shauren.trinity@gmail.com>2021-12-21 15:16:26 +0100
commit94a79bac7a06aa0f931e9d651928de7eea0a8b5c (patch)
tree0f28508689237d951d0a44ae05c85ab3a29d8c62 /src/server/game/Maps/Map.cpp
parentfe489e2be1312bc559d0c38691c9741ad69cfec8 (diff)
Core/Misc: Some refactoring, #23603 prep: (#23676)
- Split SpawnMetadata off from SpawnData - No longer allocate Creature/Gameobject objects in ObjectGridLoader just to check their typeid and delete them afterwards Co-authored-by: Giacomo Pozzoni <giacomopoz@gmail.com> (cherry picked from commit 9304e496cbf6ab6c028671fb8526c732ae5d799f)
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r--src/server/game/Maps/Map.cpp269
1 files changed, 162 insertions, 107 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 01e797e576b..32d371fe78d 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3190,75 +3190,66 @@ bool Map::CheckRespawn(RespawnInfo* info)
return true;
}
-void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId)
+void Map::Respawn(RespawnInfo* info, CharacterDatabaseTransaction dbTrans)
{
- if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler
- return;
+ info->respawnTime = GameTime::GetGameTime();
+ SaveRespawnInfoDB(*info, dbTrans);
+}
+size_t Map::DespawnAll(SpawnObjectType type, ObjectGuid::LowType spawnId)
+{
+ std::vector<WorldObject*> toUnload;
switch (type)
{
case SPAWN_TYPE_CREATURE:
- {
- Creature* obj = new Creature();
- if (!obj->LoadFromDB(spawnId, this, true, true))
- delete obj;
+ for (auto const& pair : Trinity::Containers::MapEqualRange(GetCreatureBySpawnIdStore(), spawnId))
+ toUnload.push_back(pair.second);
break;
- }
case SPAWN_TYPE_GAMEOBJECT:
- {
- GameObject* obj = new GameObject();
- if (!obj->LoadFromDB(spawnId, this, true))
- delete obj;
- break;
- }
+ for (auto const& pair : Trinity::Containers::MapEqualRange(GetGameObjectBySpawnIdStore(), spawnId))
+ toUnload.push_back(pair.second);
default:
- ASSERT(false, "Invalid spawn type %u (spawnid " UI64FMTD ") on map %u", uint32(type), spawnId, GetId());
+ break;
}
-}
-void Map::Respawn(RespawnInfo* info, CharacterDatabaseTransaction dbTrans)
-{
- if (!CheckRespawn(info))
- {
- if (info->respawnTime)
- {
- _respawnTimes.decrease(info->handle);
- SaveRespawnInfoDB(*info, dbTrans);
- }
- else
- DeleteRespawnInfo(info, dbTrans);
- return;
- }
+ for (WorldObject* o : toUnload)
+ AddObjectToRemoveList(o);
- // remove the actual respawn record first - since this deletes it, we save what we need
- SpawnObjectType const type = info->type;
- uint32 const gridId = info->gridId;
- ObjectGuid::LowType const spawnId = info->spawnId;
- DeleteRespawnInfo(info, dbTrans);
- DoRespawn(type, spawnId, gridId);
+ return toUnload.size();
}
bool Map::AddRespawnInfo(RespawnInfo const& info)
{
- ASSERT(info.spawnId, "Attempt to schedule respawn with zero spawnid (type %u)", uint32(info.type));
+ if (!info.spawnId)
+ {
+ TC_LOG_ERROR("maps", "Attempt to insert respawn info for zero spawn id (type %u)", uint32(info.type));
+ return false;
+ }
- RespawnInfoMap& bySpawnIdMap = GetRespawnMapForType(info.type);
+ RespawnInfoMap* bySpawnIdMap = GetRespawnMapForType(info.type);
+ if (!bySpawnIdMap)
+ return false;
- auto it = bySpawnIdMap.find(info.spawnId);
- if (it != bySpawnIdMap.end()) // spawnid already has a respawn scheduled
+ // check if we already have the maximum possible number of respawns scheduled
+ if (SpawnData::TypeHasData(info.type))
{
- RespawnInfo* const existing = it->second;
- if (info.respawnTime < existing->respawnTime) // delete existing in this case
- DeleteRespawnInfo(existing);
- else
- return false;
+ auto it = bySpawnIdMap->find(info.spawnId);
+ if (it != bySpawnIdMap->end()) // spawnid already has a respawn scheduled
+ {
+ RespawnInfo* const existing = it->second;
+ if (info.respawnTime <= existing->respawnTime) // delete existing in this case
+ DeleteRespawnInfo(existing);
+ else
+ return false;
+ }
+ ASSERT(bySpawnIdMap->find(info.spawnId) == bySpawnIdMap->end(), "Insertion of respawn info with id (%u," UI64FMTD ") into spawn id map failed - state desync.", uint32(info.type), info.spawnId);
}
+ else
+ ASSERT(false, "Invalid respawn info for spawn id (%u," UI64FMTD ") being inserted", uint32(info.type), info.spawnId);
- // if we get to this point, we should insert the respawninfo (there either was no prior entry, or it was deleted already)
RespawnInfo * ri = new RespawnInfo(info);
ri->handle = _respawnTimes.push(ri);
- bool success = bySpawnIdMap.emplace(ri->spawnId, ri).second;
- ASSERT(success, "Insertion of respawn info with id (%u," UI64FMTD ") into spawn id map failed - state desync.", uint32(ri->type), ri->spawnId);
+ bySpawnIdMap->emplace(ri->spawnId, ri);
return true;
}
@@ -3279,9 +3270,11 @@ void Map::GetRespawnInfo(std::vector<RespawnInfo*>& respawnData, SpawnObjectType
RespawnInfo* Map::GetRespawnInfo(SpawnObjectType type, ObjectGuid::LowType spawnId) const
{
- RespawnInfoMap const& map = GetRespawnMapForType(type);
- auto it = map.find(spawnId);
- if (it == map.end())
+ RespawnInfoMap const* map = GetRespawnMapForType(type);
+ if (!map)
+ return nullptr;
+ auto it = map->find(spawnId);
+ if (it == map->end())
return nullptr;
return it->second;
}
@@ -3301,8 +3294,14 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, CharacterDatabaseTransaction dbTr
ASSERT(info);
// spawnid store
- size_t const n = GetRespawnMapForType(info->type).erase(info->spawnId);
- ASSERT(n == 1, "Respawn stores inconsistent for map %u, spawnid " UI64FMTD " (type %u)", GetId(), info->spawnId, uint32(info->type));
+ auto spawnMap = GetRespawnMapForType(info->type);
+ if (!spawnMap)
+ return;
+
+ auto range = spawnMap->equal_range(info->spawnId);
+ auto it = std::find_if(range.first, range.second, [info](RespawnInfoMap::value_type const& pair) { return (pair.second == info); });
+ ASSERT(it != range.second, "Respawn stores inconsistent for map %u, spawnid " UI64FMTD " (type %u)", GetId(), info->spawnId, uint32(info->type));
+ spawnMap->erase(it);
// respawn heap
_respawnTimes.erase(info->handle);
@@ -3319,6 +3318,32 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, CharacterDatabaseTransaction dbTr
delete info;
}
+void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId)
+{
+ if (!IsGridLoaded(gridId)) // if grid isn't loaded, this will be processed in grid load handler
+ return;
+
+ switch (type)
+ {
+ case SPAWN_TYPE_CREATURE:
+ {
+ Creature* obj = new Creature();
+ if (!obj->LoadFromDB(spawnId, this, true, true))
+ delete obj;
+ break;
+ }
+ case SPAWN_TYPE_GAMEOBJECT:
+ {
+ GameObject* obj = new GameObject();
+ if (!obj->LoadFromDB(spawnId, this, true))
+ delete obj;
+ break;
+ }
+ default:
+ ASSERT(false, "Invalid spawn type %u (spawnid " UI64FMTD ") on map %u", uint32(type), spawnId, GetId());
+ }
+}
+
void Map::ProcessRespawns()
{
time_t now = GameTime::GetGameTime();
@@ -3331,14 +3356,14 @@ void Map::ProcessRespawns()
{
// ok, respawn
_respawnTimes.pop();
- GetRespawnMapForType(next->type).erase(next->spawnId);
+ ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
DoRespawn(next->type, next->spawnId, next->gridId);
delete next;
}
else if (!next->respawnTime) // just remove respawn entry without rescheduling
{
_respawnTimes.pop();
- GetRespawnMapForType(next->type).erase(next->spawnId);
+ ASSERT_NOTNULL(GetRespawnMapForType(next->type))->erase(next->spawnId);
delete next;
}
else // value changed, update heap position
@@ -3371,8 +3396,11 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low
return;
}
- SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId);
- if (!data || !data->spawnGroupData || !(data->spawnGroupData->flags & SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE))
+ SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId);
+ if (!data)
+ return;
+
+ if (!(data->spawnGroupData->flags & SPAWNGROUP_FLAG_DYNAMIC_SPAWN_RATE))
return;
auto it = _zonePlayerCountMap.find(obj->GetZoneId());
@@ -3391,6 +3419,23 @@ void Map::ApplyDynamicModeRespawnScaling(WorldObject const* obj, ObjectGuid::Low
respawnDelay = std::max<uint32>(ceil(respawnDelay * adjustFactor), timeMinimum);
}
+bool Map::ShouldBeSpawnedOnGridLoad(SpawnObjectType type, ObjectGuid::LowType spawnId) const
+{
+ ASSERT(SpawnData::TypeHasData(type));
+ // check if the object is on its respawn timer
+ if (GetRespawnTime(type, spawnId))
+ return false;
+
+ SpawnMetadata const* spawnData = ASSERT_NOTNULL(sObjectMgr->GetSpawnMetadata(type, spawnId));
+ // check if the object is part of a spawn group
+ SpawnGroupTemplateData const* spawnGroup = ASSERT_NOTNULL(spawnData->spawnGroupData);
+ if (!(spawnGroup->flags & SPAWNGROUP_FLAG_SYSTEM))
+ if (!IsSpawnGroupActive(spawnGroup->groupId))
+ return false;
+
+ return true;
+}
+
SpawnGroupTemplateData const* Map::GetSpawnGroupData(uint32 groupId) const
{
SpawnGroupTemplateData const* data = sObjectMgr->GetSpawnGroupData(groupId);
@@ -3409,31 +3454,44 @@ bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::v
}
SetSpawnGroupActive(groupId, true); // start processing respawns for the group
- for (auto& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
- {
- SpawnData const* data = pair.second;
- ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
- // Check if there's already an instance spawned
- if (!force)
- if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId))
- if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive())
- continue;
- time_t respawnTime = GetRespawnTime(data->type, data->spawnId);
- if (respawnTime)
+ std::vector<SpawnData const*> toSpawn;
+ for (auto& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId))
+ {
+ SpawnMetadata const* data = pair.second;
+ ASSERT(groupData->mapId == data->mapId);
+
+ auto respawnMap = GetRespawnMapForType(data->type);
+ if (!respawnMap)
+ continue;
+
+ if (force || ignoreRespawn)
+ RemoveRespawnTime(data->type, data->spawnId);
+
+ uint32 nRespawnTimers = respawnMap->count(data->spawnId);
+ if (SpawnData::TypeHasData(data->type))
{
- if (!force && !ignoreRespawn && (respawnTime > GameTime::GetGameTime()))
+ // has a respawn timer
+ if (nRespawnTimers)
continue;
- // we need to remove the respawn time, otherwise we'd end up double spawning
- RemoveRespawnTime(data->type, data->spawnId);
+ // has a spawn already active
+ if (!force)
+ if (WorldObject* obj = GetWorldObjectBySpawnId(data->type, data->spawnId))
+ if ((data->type != SPAWN_TYPE_CREATURE) || obj->ToCreature()->IsAlive())
+ continue;
+
+ toSpawn.push_back(ASSERT_NOTNULL(data->ToSpawnData()));
}
+ }
+ for (SpawnData const* data : toSpawn)
+ {
// don't spawn if the grid isn't loaded (will be handled in grid loader)
if (!IsGridLoaded(data->spawnPoint))
continue;
- // Everything OK, now do the actual (re)spawn
+ // now do the actual (re)spawn
switch (data->type)
{
case SPAWN_TYPE_CREATURE:
@@ -3454,6 +3512,15 @@ bool Map::SpawnGroupSpawn(uint32 groupId, bool ignoreRespawn, bool force, std::v
spawnedObjects->push_back(gameobject);
break;
}
+ case SPAWN_TYPE_AREATRIGGER:
+ {
+ AreaTrigger* areaTrigger = new AreaTrigger();
+ if (!areaTrigger->LoadFromDB(data->spawnId, this, true, false))
+ delete areaTrigger;
+ else if (spawnedObjects)
+ spawnedObjects->push_back(areaTrigger);
+ break;
+ }
default:
ASSERT(false, "Invalid spawn type %u with spawnId " UI64FMTD, uint32(data->type), data->spawnId);
return false;
@@ -3471,41 +3538,16 @@ bool Map::SpawnGroupDespawn(uint32 groupId, bool deleteRespawnTimes, size_t* cou
return false;
}
- std::vector<WorldObject*> toUnload; // unload after iterating, otherwise iterator invalidation
- for (auto const& pair : sObjectMgr->GetSpawnDataForGroup(groupId))
+ for (auto const& pair : sObjectMgr->GetSpawnMetadataForGroup(groupId))
{
- SpawnData const* data = pair.second;
- ASSERT(groupData->mapId == data->spawnPoint.GetMapId());
+ SpawnMetadata const* data = pair.second;
+ ASSERT(groupData->mapId == data->mapId);
if (deleteRespawnTimes)
RemoveRespawnTime(data->type, data->spawnId);
- switch (data->type)
- {
- case SPAWN_TYPE_CREATURE:
- {
- auto bounds = GetCreatureBySpawnIdStore().equal_range(data->spawnId);
- for (auto it = bounds.first; it != bounds.second; ++it)
- toUnload.emplace_back(it->second);
- break;
- }
- case SPAWN_TYPE_GAMEOBJECT:
- {
- auto bounds = GetGameObjectBySpawnIdStore().equal_range(data->spawnId);
- for (auto it = bounds.first; it != bounds.second; ++it)
- toUnload.emplace_back(it->second);
- break;
- }
- default:
- ASSERT(false, "Invalid spawn type %u in spawn data with spawnId " UI64FMTD ".", uint32(data->type), data->spawnId);
- return false;
- }
+ size_t c = DespawnAll(data->type, data->spawnId);
+ if (count)
+ *count += c;
}
-
- if (count)
- *count = toUnload.size();
-
- // now do the actual despawning
- for (WorldObject* obj : toUnload)
- obj->AddObjectToRemoveList();
SetSpawnGroupActive(groupId, false); // stop processing respawns for the group, too
return true;
}
@@ -4489,6 +4531,15 @@ GameObject* Map::GetGameObjectBySpawnId(ObjectGuid::LowType spawnId) const
return creatureItr != bounds.second ? creatureItr->second : bounds.first->second;
}
+AreaTrigger* Map::GetAreaTriggerBySpawnId(ObjectGuid::LowType spawnId) const
+{
+ auto const bounds = GetAreaTriggerBySpawnIdStore().equal_range(spawnId);
+ if (bounds.first == bounds.second)
+ return nullptr;
+
+ return bounds.first->second;
+}
+
void Map::UpdateIteratorBack(Player* player)
{
if (m_mapRefIter == player->GetMapRef())
@@ -4497,19 +4548,23 @@ void Map::UpdateIteratorBack(Player* player)
void Map::SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, CharacterDatabaseTransaction dbTrans, bool startup)
{
- if (!spawnId)
+ SpawnMetadata const* data = sObjectMgr->GetSpawnMetadata(type, spawnId);
+ if (!data)
+ {
+ TC_LOG_ERROR("maps", "Map %u attempt to save respawn time for nonexistant spawnid (%u," UI64FMTD ").", GetId(), type, spawnId);
return;
+ }
if (!respawnTime)
{
// Delete only
- RemoveRespawnTime(type, spawnId, dbTrans);
+ RemoveRespawnTime(data->type, data->spawnId, dbTrans);
return;
}
RespawnInfo ri;
- ri.type = type;
- ri.spawnId = spawnId;
+ ri.type = data->type;
+ ri.spawnId = data->spawnId;
ri.entry = entry;
ri.respawnTime = respawnTime;
ri.gridId = gridId;
@@ -4549,7 +4604,7 @@ void Map::LoadRespawnTimes()
ObjectGuid::LowType spawnId = fields[1].GetUInt64();
time_t respawnTime = fields[2].GetInt64();
- if (type < SPAWN_TYPE_MAX)
+ if (SpawnData::TypeHasData(type))
{
if (SpawnData const* data = sObjectMgr->GetSpawnData(type, spawnId))
SaveRespawnTime(type, spawnId, data->id, time_t(respawnTime), Trinity::ComputeGridCoord(data->spawnPoint.GetPositionX(), data->spawnPoint.GetPositionY()).GetId(), nullptr, true);