Core/Misc: Various dynspawn cleanup and refactors split off from pooling rewrite:

Port From (https://github.com/TrinityCore/TrinityCore/commit/eee950cdd7bcbe9443a53ea5c4cce35444a503f7)
This commit is contained in:
hondacrx
2021-12-27 18:09:58 -05:00
parent 9b2d1e67b6
commit 55c298be9f
6 changed files with 92 additions and 94 deletions
@@ -253,7 +253,7 @@ namespace Game.AI
if (!isEscort) if (!isEscort)
me.DespawnOrUnsummon(0, TimeSpan.FromSeconds(1)); me.DespawnOrUnsummon(0, TimeSpan.FromSeconds(1));
else else
me.GetMap().RemoveRespawnTime(SpawnObjectType.Creature, me.GetSpawnId(), true); me.GetMap().Respawn(SpawnObjectType.Creature, me.GetSpawnId());
} }
else else
me.DespawnOrUnsummon(); me.DespawnOrUnsummon();
+1 -1
View File
@@ -2359,7 +2359,7 @@ namespace Game.AI
map = targets.First().GetMap(); map = targets.First().GetMap();
if (map) if (map)
map.RemoveRespawnTime((SpawnObjectType)e.Action.respawnData.spawnType, e.Action.respawnData.spawnId, true); map.Respawn((SpawnObjectType)e.Action.respawnData.spawnType, e.Action.respawnData.spawnId);
else else
Log.outError(LogFilter.Sql, $"SmartScript.ProcessAction: Entry {e.EntryOrGuid} SourceType {e.GetScriptType()}, Event {e.EventId} - tries to respawn by spawnId but does not provide a map"); Log.outError(LogFilter.Sql, $"SmartScript.ProcessAction: Entry {e.EntryOrGuid} SourceType {e.GetScriptType()}, Event {e.EventId} - tries to respawn by spawnId but does not provide a map");
break; break;
+1 -1
View File
@@ -1959,7 +1959,7 @@ namespace Game.Chat
uint gridId = GridDefines.ComputeGridCoord(player.GetPositionX(), player.GetPositionY()).GetId(); uint gridId = GridDefines.ComputeGridCoord(player.GetPositionX(), player.GetPositionY()).GetId();
foreach (RespawnInfo info in data) foreach (RespawnInfo info in data)
if (info.gridId == gridId) if (info.gridId == gridId)
player.GetMap().RemoveRespawnTime(info, true); player.GetMap().RemoveRespawnTime(info.type, info.spawnId);
} }
return true; return true;
+7 -6
View File
@@ -1625,7 +1625,7 @@ namespace Game.Entities
foreach (Creature creature in toUnload) foreach (Creature creature in toUnload)
map.AddObjectToRemoveList(creature); map.AddObjectToRemoveList(creature);
map.RemoveRespawnTime(SpawnObjectType.Creature, spawnId, false, trans); map.RemoveRespawnTime(SpawnObjectType.Creature, spawnId, trans);
}); });
// delete data from memory ... // delete data from memory ...
@@ -1897,9 +1897,6 @@ namespace Game.Entities
if (GetDeathState() == DeathState.Dead) if (GetDeathState() == DeathState.Dead)
{ {
if (m_spawnId != 0)
GetMap().RemoveRespawnTime(SpawnObjectType.Creature, m_spawnId);
Log.outDebug(LogFilter.Unit, "Respawning creature {0} ({1})", GetName(), GetGUID().ToString()); Log.outDebug(LogFilter.Unit, "Respawning creature {0} ({1})", GetName(), GetGUID().ToString());
m_respawnTime = 0; m_respawnTime = 0;
ResetPickPocketRefillTimer(); ResetPickPocketRefillTimer();
@@ -1939,7 +1936,7 @@ namespace Game.Entities
else else
{ {
if (m_spawnId != 0) if (m_spawnId != 0)
GetMap().RemoveRespawnTime(SpawnObjectType.Creature, m_spawnId, true); GetMap().Respawn(SpawnObjectType.Creature, m_spawnId);
} }
Log.outDebug(LogFilter.Unit, $"Respawning creature {GetName()} ({GetGUID()})"); Log.outDebug(LogFilter.Unit, $"Respawning creature {GetName()} ({GetGUID()})");
@@ -2268,7 +2265,11 @@ namespace Game.Entities
if (m_respawnCompatibilityMode) if (m_respawnCompatibilityMode)
{ {
GetMap().SaveRespawnTimeDB(SpawnObjectType.Creature, m_spawnId, m_respawnTime); RespawnInfo ri = new();
ri.type = SpawnObjectType.Creature;
ri.spawnId = m_spawnId;
ri.respawnTime = m_respawnTime;
GetMap().SaveRespawnInfoDB(ri);
return; return;
} }
@@ -1164,7 +1164,7 @@ namespace Game.Entities
foreach (GameObject obj in toUnload) foreach (GameObject obj in toUnload)
map.AddObjectToRemoveList(obj); map.AddObjectToRemoveList(obj);
map.RemoveRespawnTime(SpawnObjectType.GameObject, spawnId, false, trans); map.RemoveRespawnTime(SpawnObjectType.GameObject, spawnId, trans);
}); });
// delete data from memory // delete data from memory
@@ -1271,7 +1271,11 @@ namespace Game.Entities
{ {
if (m_respawnCompatibilityMode) if (m_respawnCompatibilityMode)
{ {
GetMap().SaveRespawnTimeDB(SpawnObjectType.GameObject, m_spawnId, m_respawnTime); RespawnInfo ri = new();
ri.type = SpawnObjectType.GameObject;
ri.spawnId = m_spawnId;
ri.respawnTime = m_respawnTime;
GetMap().SaveRespawnInfoDB(ri);
return; return;
} }
@@ -1337,7 +1341,7 @@ namespace Game.Entities
if (m_spawnedByDefault && m_respawnTime > 0) if (m_spawnedByDefault && m_respawnTime > 0)
{ {
m_respawnTime = GameTime.GetGameTime(); m_respawnTime = GameTime.GetGameTime();
GetMap().RemoveRespawnTime(SpawnObjectType.GameObject, m_spawnId, true); GetMap().Respawn(SpawnObjectType.GameObject, m_spawnId);
} }
} }
+69 -76
View File
@@ -93,7 +93,7 @@ namespace Game.Maps
// Delete all waiting spawns // Delete all waiting spawns
// This doesn't delete from database. // This doesn't delete from database.
DeleteRespawnInfo(); UnloadAllRespawnInfos();
for (var i = 0; i < i_worldObjects.Count; ++i) for (var i = 0; i < i_worldObjects.Count; ++i)
{ {
@@ -2434,14 +2434,24 @@ namespace Game.Maps
} }
} }
void Respawn(RespawnInfo info, SQLTransaction dbTrans = null) public void Respawn(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null)
Respawn(info, dbTrans);
}
public void Respawn(RespawnInfo info, SQLTransaction dbTrans = null)
{ {
if (!CheckRespawn(info)) if (!CheckRespawn(info))
{ {
if (info.respawnTime != 0) if (info.respawnTime != 0)
SaveRespawnTime(info.type, info.spawnId, info.entry, info.respawnTime, info.zoneId, info.gridId, true, true, dbTrans); {
//_respawnTimes.decrease(info);
SaveRespawnInfoDB(info, dbTrans);
}
else else
RemoveRespawnTime(info); DeleteRespawnInfo(info, dbTrans);
return; return;
} }
@@ -2450,43 +2460,31 @@ namespace Game.Maps
SpawnObjectType type = info.type; SpawnObjectType type = info.type;
uint gridId = info.gridId; uint gridId = info.gridId;
ulong spawnId = info.spawnId; ulong spawnId = info.spawnId;
RemoveRespawnTime(info); DeleteRespawnInfo(info, dbTrans);
DoRespawn(type, spawnId, gridId); DoRespawn(type, spawnId, gridId);
} }
void Respawn(List<RespawnInfo> respawnData, SQLTransaction dbTrans) bool AddRespawnInfo(RespawnInfo info)
{ {
SQLTransaction trans = dbTrans != null ? dbTrans : new SQLTransaction(); Cypher.Assert(info.spawnId != 0, $"Attempt to schedule respawn with zero spawnid (type {info.type})");
foreach (RespawnInfo info in respawnData)
Respawn(info, trans);
if (dbTrans == null)
DB.Characters.CommitTransaction(trans);
}
void AddRespawnInfo(RespawnInfo info, bool replace)
{
if (info.spawnId == 0)
return;
var bySpawnIdMap = GetRespawnMapForType(info.type); var bySpawnIdMap = GetRespawnMapForType(info.type);
var existing = bySpawnIdMap.LookupByKey(info.spawnId); var existing = bySpawnIdMap.LookupByKey(info.spawnId);
if (existing != null) // spawnid already has a respawn scheduled if (existing != null) // spawnid already has a respawn scheduled
{ {
if (replace || info.respawnTime < existing.respawnTime) // delete existing in this case if (info.respawnTime < existing.respawnTime) // delete existing in this case
DeleteRespawnInfo(existing); DeleteRespawnInfo(existing);
else // don't delete existing, instead replace respawn time so caller saves the correct time else
{ return false;
info.respawnTime = existing.respawnTime;
return;
}
} }
// if we get to this point, we should insert the respawninfo (there either was no prior entry, or it was deleted already) // 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(info); RespawnInfo ri = new(info);
_respawnTimes.Add(ri); _respawnTimes.Add(ri);
bySpawnIdMap.Add(ri.spawnId, ri); bool success = bySpawnIdMap.TryAdd(ri.spawnId, ri);
Cypher.Assert(success, $"Insertion of respawn info with id ({ri.type},{ri.spawnId}) into spawn id map failed - state desync.");
return true;
} }
static void PushRespawnInfoFrom(List<RespawnInfo> data, Dictionary<ulong, RespawnInfo> map, uint zoneId) static void PushRespawnInfoFrom(List<RespawnInfo> data, Dictionary<ulong, RespawnInfo> map, uint zoneId)
@@ -2516,14 +2514,14 @@ namespace Game.Maps
Dictionary<ulong, RespawnInfo> GetRespawnMapForType(SpawnObjectType type) { return (type == SpawnObjectType.GameObject) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; } Dictionary<ulong, RespawnInfo> GetRespawnMapForType(SpawnObjectType type) { return (type == SpawnObjectType.GameObject) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; }
void DeleteRespawnInfo() // delete everything void UnloadAllRespawnInfos() // delete everything from memory
{ {
_respawnTimes.Clear(); _respawnTimes.Clear();
_creatureRespawnTimesBySpawnId.Clear(); _creatureRespawnTimesBySpawnId.Clear();
_gameObjectRespawnTimesBySpawnId.Clear(); _gameObjectRespawnTimesBySpawnId.Clear();
} }
void DeleteRespawnInfo(RespawnInfo info) void DeleteRespawnInfo(RespawnInfo info, SQLTransaction dbTrans = null)
{ {
// Delete from all relevant containers to ensure consistency // Delete from all relevant containers to ensure consistency
Cypher.Assert(info != null); Cypher.Assert(info != null);
@@ -2534,46 +2532,21 @@ namespace Game.Maps
// respawn heap // respawn heap
_respawnTimes.Remove(info); _respawnTimes.Remove(info);
}
public void RemoveRespawnTime(RespawnInfo info, bool doRespawn = false, SQLTransaction dbTrans = null) // database
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESPAWN); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESPAWN);
stmt.AddValue(0, (ushort)info.type); stmt.AddValue(0, (ushort)info.type);
stmt.AddValue(1, info.spawnId); stmt.AddValue(1, info.spawnId);
stmt.AddValue(2, GetId()); stmt.AddValue(2, GetId());
stmt.AddValue(3, GetInstanceId()); stmt.AddValue(3, GetInstanceId());
DB.Characters.ExecuteOrAppend(dbTrans, stmt); DB.Characters.ExecuteOrAppend(dbTrans, stmt);
if (doRespawn)
Respawn(info);
else
DeleteRespawnInfo(info);
} }
public void RemoveRespawnTime(List<RespawnInfo> respawnData, bool doRespawn, SQLTransaction dbTrans = null) public void RemoveRespawnTime(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null)
{
SQLTransaction trans = dbTrans != null ? dbTrans : new SQLTransaction();
foreach (RespawnInfo info in respawnData)
RemoveRespawnTime(info, doRespawn, trans);
if (dbTrans == null)
DB.Characters.CommitTransaction(trans);
}
public void RemoveRespawnTime(SpawnObjectTypeMask types = SpawnObjectTypeMask.All, uint zoneId = 0, bool doRespawn = false, SQLTransaction dbTrans = null)
{
List<RespawnInfo> v = new();
GetRespawnInfo(v, types, zoneId);
if (!v.Empty())
RemoveRespawnTime(v, doRespawn, dbTrans);
}
public void RemoveRespawnTime(SpawnObjectType type, ulong spawnId, bool doRespawn = false, SQLTransaction dbTrans = null)
{ {
RespawnInfo info = GetRespawnInfo(type, spawnId); RespawnInfo info = GetRespawnInfo(type, spawnId);
if (info != null) if (info != null)
RemoveRespawnTime(info, doRespawn, dbTrans); DeleteRespawnInfo(info, dbTrans);
} }
void ProcessRespawns() void ProcessRespawns()
@@ -2601,6 +2574,7 @@ namespace Game.Maps
{ {
Cypher.Assert(now < next.respawnTime); // infinite loop guard Cypher.Assert(now < next.respawnTime); // infinite loop guard
//_respawnTimes.decrease(next.handle); //_respawnTimes.decrease(next.handle);
SaveRespawnInfoDB(next);
} }
} }
} }
@@ -2686,7 +2660,7 @@ namespace Game.Maps
continue; continue;
// we need to remove the respawn time, otherwise we'd end up double spawning // we need to remove the respawn time, otherwise we'd end up double spawning
RemoveRespawnTime(data.type, data.spawnId, false); RemoveRespawnTime(data.type, data.spawnId);
} }
// don't spawn if the grid isn't loaded (will be handled in grid loader) // don't spawn if the grid isn't loaded (will be handled in grid loader)
@@ -3051,12 +3025,15 @@ namespace Game.Maps
m_activeNonPlayers.Remove(obj); m_activeNonPlayers.Remove(obj);
} }
public void SaveRespawnTime(SpawnObjectType type, ulong spawnId, uint entry, long respawnTime, uint zoneId, uint gridId = 0, bool writeDB = true, bool replace = false, SQLTransaction dbTrans = null) public void SaveRespawnTime(SpawnObjectType type, ulong spawnId, uint entry, long respawnTime, uint zoneId, uint gridId = 0, SQLTransaction dbTrans = null, bool startup = false)
{ {
if (spawnId == 0)
return;
if (respawnTime == 0) if (respawnTime == 0)
{ {
// Delete only // Delete only
RemoveRespawnTime(type, spawnId, false, dbTrans); RemoveRespawnTime(type, spawnId, dbTrans);
return; return;
} }
@@ -3067,19 +3044,24 @@ namespace Game.Maps
ri.respawnTime = respawnTime; ri.respawnTime = respawnTime;
ri.gridId = gridId; ri.gridId = gridId;
ri.zoneId = zoneId; ri.zoneId = zoneId;
AddRespawnInfo(ri, replace); bool success = AddRespawnInfo(ri);
if (writeDB) if (startup)
SaveRespawnTimeDB(type, spawnId, ri.respawnTime, dbTrans); // might be different from original respawn time if we didn't replace {
if (!success)
Log.outError(LogFilter.Maps, $"Attempt to load saved respawn {respawnTime} for ({type},{spawnId}) failed - duplicate respawn? Skipped.");
}
else if (success)
SaveRespawnInfoDB(ri, dbTrans);
} }
public void SaveRespawnTimeDB(SpawnObjectType type, ulong spawnId, long respawnTime, SQLTransaction dbTrans = null) public void SaveRespawnInfoDB(RespawnInfo info, SQLTransaction dbTrans = null)
{ {
// Just here for support of compatibility mode // Just here for support of compatibility mode
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.REP_RESPAWN); PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.REP_RESPAWN);
stmt.AddValue(0, (ushort)type); stmt.AddValue(0, (ushort)info.type);
stmt.AddValue(0, spawnId); stmt.AddValue(0, info.spawnId);
stmt.AddValue(1, respawnTime); stmt.AddValue(1, info.respawnTime);
stmt.AddValue(2, GetId()); stmt.AddValue(2, GetId());
stmt.AddValue(3, GetInstanceId()); stmt.AddValue(3, GetInstanceId());
DB.Characters.ExecuteOrAppend(dbTrans, stmt); DB.Characters.ExecuteOrAppend(dbTrans, stmt);
@@ -3099,21 +3081,24 @@ namespace Game.Maps
var spawnId = result.Read<ulong>(1); var spawnId = result.Read<ulong>(1);
var respawnTime = result.Read<long>(2); var respawnTime = result.Read<long>(2);
if (type < SpawnObjectType.Max)
{
SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId); SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId);
if (data != null) if (data != null)
SaveRespawnTime(type, spawnId, data.Id, respawnTime, GetZoneId(PhasingHandler.EmptyPhaseShift, data.spawnPoint), GridDefines.ComputeGridCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY()).GetId(), false); SaveRespawnTime(type, spawnId, data.Id, respawnTime, GetZoneId(PhasingHandler.EmptyPhaseShift, data.spawnPoint), GridDefines.ComputeGridCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY()).GetId(), null, true);
else else
Log.outError(LogFilter.Maps, $"Loading saved respawn time of {respawnTime} for spawnid ({type},{spawnId}) - spawn does not exist, ignoring"); Log.outError(LogFilter.Maps, $"Loading saved respawn time of {respawnTime} for spawnid ({type},{spawnId}) - spawn does not exist, ignoring");
}
else
Log.outError(LogFilter.Maps, $"Loading saved respawn time of {respawnTime} for spawnid ({type},{spawnId}) - invalid spawn type, ignoring");
} while (result.NextRow()); } while (result.NextRow());
} }
} }
public long GetRespawnTime(SpawnObjectType type, ulong spawnId) { return (type == SpawnObjectType.GameObject) ? GetGORespawnTime(spawnId) : GetCreatureRespawnTime(spawnId); }
public void DeleteRespawnTimes() public void DeleteRespawnTimes()
{ {
DeleteRespawnInfo(); UnloadAllRespawnInfos();
DeleteRespawnTimesInDB(GetId(), GetInstanceId()); DeleteRespawnTimesInDB(GetId(), GetInstanceId());
} }
@@ -3754,15 +3739,15 @@ namespace Game.Maps
return 0; return 0;
} }
public long GetCreatureRespawnTime(ulong dbGuid) public long GetRespawnTime(SpawnObjectType type, ulong spawnId)
{ {
return _creatureRespawnTimesBySpawnId.ContainsKey(dbGuid) ? _creatureRespawnTimesBySpawnId[dbGuid].respawnTime : 0; var respawnDic = GetRespawnMapForType(type);
var respawnInfo = respawnDic.LookupByKey(spawnId);
return (respawnInfo == null) ? 0 : respawnInfo.respawnTime;
} }
public long GetGORespawnTime(ulong dbGuid) public long GetCreatureRespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.Creature, spawnId); }
{ public long GetGORespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.GameObject, spawnId); }
return _gameObjectRespawnTimesBySpawnId.ContainsKey(dbGuid) ? _gameObjectRespawnTimesBySpawnId[dbGuid].respawnTime : 0;
}
void SetTimer(uint t) void SetTimer(uint t)
{ {
@@ -3883,7 +3868,15 @@ namespace Game.Maps
public WorldObject GetWorldObjectBySpawnId(SpawnObjectType type, ulong spawnId) public WorldObject GetWorldObjectBySpawnId(SpawnObjectType type, ulong spawnId)
{ {
return type == SpawnObjectType.GameObject ? (WorldObject)GetGameObjectBySpawnId(spawnId) : (WorldObject)GetCreatureBySpawnId(spawnId); switch (type)
{
case SpawnObjectType.Creature:
return GetCreatureBySpawnId(spawnId);
case SpawnObjectType.GameObject:
return GetGameObjectBySpawnId(spawnId);
default:
return null;
}
} }
public void Visit(Cell cell, Visitor visitor) public void Visit(Cell cell, Visitor visitor)