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
committerGitHub <noreply@github.com>2020-02-08 20:22:37 +0100
commit9304e496cbf6ab6c028671fb8526c732ae5d799f (patch)
tree997040bf14477bbd30b9b175aac93fa287de03e1 /src/server/game/Maps/Map.cpp
parent726d5e91b55d4742dcbd6b0a82d84788dbb117b7 (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>
Diffstat (limited to 'src/server/game/Maps/Map.cpp')
-rw-r--r--src/server/game/Maps/Map.cpp229
1 files changed, 128 insertions, 101 deletions
diff --git a/src/server/game/Maps/Map.cpp b/src/server/game/Maps/Map.cpp
index 8001aa66412..9569b587112 100644
--- a/src/server/game/Maps/Map.cpp
+++ b/src/server/game/Maps/Map.cpp
@@ -3026,75 +3026,64 @@ bool Map::CheckRespawn(RespawnInfo* info)
return true;
}
-void Map::DoRespawn(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 gridId)
+void Map::Respawn(RespawnInfo* info, SQLTransaction 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 %u) on map %u", uint32(type), spawnId, GetId());
+ break;
}
-}
-void Map::Respawn(RespawnInfo* info, SQLTransaction 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);
- 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,%u) into spawn id map failed - state desync.", uint32(info.type), info.spawnId);
}
+ else
+ ASSERT(false, "Invalid respawn info for spawn id (%u,%u) 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,%u) into spawn id map failed - state desync.", uint32(ri->type), ri->spawnId);
+ bySpawnIdMap.emplace(ri->spawnId, ri);
return true;
}
@@ -3137,8 +3126,11 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, SQLTransaction dbTrans)
ASSERT(info);
// spawnid store
- size_t const n = GetRespawnMapForType(info->type).erase(info->spawnId);
- ASSERT(n == 1, "Respawn stores inconsistent for map %u, spawnid %u (type %u)", GetId(), info->spawnId, uint32(info->type));
+ auto& spawnMap = GetRespawnMapForType(info->type);
+ 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 %u (type %u)", GetId(), info->spawnId, uint32(info->type));
+ spawnMap.erase(it);
// respawn heap
_respawnTimes.erase(info->handle);
@@ -3155,6 +3147,32 @@ void Map::DeleteRespawnInfo(RespawnInfo* info, SQLTransaction dbTrans)
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 %u) on map %u", uint32(type), spawnId, GetId());
+ }
+}
+
void Map::ProcessRespawns()
{
time_t now = GameTime::GetGameTime();
@@ -3207,8 +3225,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());
@@ -3227,6 +3248,24 @@ 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);
@@ -3245,31 +3284,40 @@ 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);
+
+ if (force || ignoreRespawn)
+ RemoveRespawnTime(data->type, data->spawnId);
+
+ uint32 nRespawnTimers = GetRespawnMapForType(data->type).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:
@@ -3307,41 +3355,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 %u.", 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;
}
@@ -4282,19 +4305,23 @@ void Map::UpdateIteratorBack(Player* player)
void Map::SaveRespawnTime(SpawnObjectType type, ObjectGuid::LowType spawnId, uint32 entry, time_t respawnTime, uint32 gridId, SQLTransaction 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,%u).", 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;
@@ -4334,7 +4361,7 @@ void Map::LoadRespawnTimes()
ObjectGuid::LowType spawnId = fields[1].GetUInt32();
uint64 respawnTime = fields[2].GetUInt64();
- 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);