From 55c298be9fb2012a483df117498602c236979ecb Mon Sep 17 00:00:00 2001 From: hondacrx Date: Mon, 27 Dec 2021 18:09:58 -0500 Subject: [PATCH] Core/Misc: Various dynspawn cleanup and refactors split off from pooling rewrite: Port From (https://github.com/TrinityCore/TrinityCore/commit/eee950cdd7bcbe9443a53ea5c4cce35444a503f7) --- Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs | 2 +- Source/Game/AI/SmartScripts/SmartScript.cs | 2 +- Source/Game/Chat/Commands/MiscCommands.cs | 2 +- Source/Game/Entities/Creature/Creature.cs | 13 +- Source/Game/Entities/GameObject/GameObject.cs | 10 +- Source/Game/Maps/Map.cs | 157 +++++++++--------- 6 files changed, 92 insertions(+), 94 deletions(-) diff --git a/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs b/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs index a2021763e..3060d32fe 100644 --- a/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs +++ b/Source/Game/AI/ScriptedAI/ScriptedEscortAI.cs @@ -253,7 +253,7 @@ namespace Game.AI if (!isEscort) me.DespawnOrUnsummon(0, TimeSpan.FromSeconds(1)); else - me.GetMap().RemoveRespawnTime(SpawnObjectType.Creature, me.GetSpawnId(), true); + me.GetMap().Respawn(SpawnObjectType.Creature, me.GetSpawnId()); } else me.DespawnOrUnsummon(); diff --git a/Source/Game/AI/SmartScripts/SmartScript.cs b/Source/Game/AI/SmartScripts/SmartScript.cs index 70f8b3ab8..5ed77273e 100644 --- a/Source/Game/AI/SmartScripts/SmartScript.cs +++ b/Source/Game/AI/SmartScripts/SmartScript.cs @@ -2359,7 +2359,7 @@ namespace Game.AI map = targets.First().GetMap(); 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 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; diff --git a/Source/Game/Chat/Commands/MiscCommands.cs b/Source/Game/Chat/Commands/MiscCommands.cs index c4f59105c..9ebdb9748 100644 --- a/Source/Game/Chat/Commands/MiscCommands.cs +++ b/Source/Game/Chat/Commands/MiscCommands.cs @@ -1959,7 +1959,7 @@ namespace Game.Chat uint gridId = GridDefines.ComputeGridCoord(player.GetPositionX(), player.GetPositionY()).GetId(); foreach (RespawnInfo info in data) if (info.gridId == gridId) - player.GetMap().RemoveRespawnTime(info, true); + player.GetMap().RemoveRespawnTime(info.type, info.spawnId); } return true; diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index 0d149aa63..e01520ce8 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -1625,7 +1625,7 @@ namespace Game.Entities foreach (Creature creature in toUnload) map.AddObjectToRemoveList(creature); - map.RemoveRespawnTime(SpawnObjectType.Creature, spawnId, false, trans); + map.RemoveRespawnTime(SpawnObjectType.Creature, spawnId, trans); }); // delete data from memory ... @@ -1897,9 +1897,6 @@ namespace Game.Entities 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()); m_respawnTime = 0; ResetPickPocketRefillTimer(); @@ -1939,7 +1936,7 @@ namespace Game.Entities else { 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()})"); @@ -2268,7 +2265,11 @@ namespace Game.Entities 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; } diff --git a/Source/Game/Entities/GameObject/GameObject.cs b/Source/Game/Entities/GameObject/GameObject.cs index 46420efc0..5eeecbb93 100644 --- a/Source/Game/Entities/GameObject/GameObject.cs +++ b/Source/Game/Entities/GameObject/GameObject.cs @@ -1164,7 +1164,7 @@ namespace Game.Entities foreach (GameObject obj in toUnload) map.AddObjectToRemoveList(obj); - map.RemoveRespawnTime(SpawnObjectType.GameObject, spawnId, false, trans); + map.RemoveRespawnTime(SpawnObjectType.GameObject, spawnId, trans); }); // delete data from memory @@ -1271,7 +1271,11 @@ namespace Game.Entities { 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; } @@ -1337,7 +1341,7 @@ namespace Game.Entities if (m_spawnedByDefault && m_respawnTime > 0) { m_respawnTime = GameTime.GetGameTime(); - GetMap().RemoveRespawnTime(SpawnObjectType.GameObject, m_spawnId, true); + GetMap().Respawn(SpawnObjectType.GameObject, m_spawnId); } } diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index d167de53d..21b0d2532 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -93,7 +93,7 @@ namespace Game.Maps // Delete all waiting spawns // This doesn't delete from database. - DeleteRespawnInfo(); + UnloadAllRespawnInfos(); 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 (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 - RemoveRespawnTime(info); + DeleteRespawnInfo(info, dbTrans); return; } @@ -2450,43 +2460,31 @@ namespace Game.Maps SpawnObjectType type = info.type; uint gridId = info.gridId; ulong spawnId = info.spawnId; - RemoveRespawnTime(info); + DeleteRespawnInfo(info, dbTrans); DoRespawn(type, spawnId, gridId); } - void Respawn(List respawnData, SQLTransaction dbTrans) + bool AddRespawnInfo(RespawnInfo info) { - SQLTransaction trans = dbTrans != null ? dbTrans : new SQLTransaction(); - 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; + Cypher.Assert(info.spawnId != 0, $"Attempt to schedule respawn with zero spawnid (type {info.type})"); var bySpawnIdMap = GetRespawnMapForType(info.type); var existing = bySpawnIdMap.LookupByKey(info.spawnId); 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); - else // don't delete existing, instead replace respawn time so caller saves the correct time - { - info.respawnTime = existing.respawnTime; - return; - } + else + return false; } // 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); _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 data, Dictionary map, uint zoneId) @@ -2516,14 +2514,14 @@ namespace Game.Maps Dictionary GetRespawnMapForType(SpawnObjectType type) { return (type == SpawnObjectType.GameObject) ? _gameObjectRespawnTimesBySpawnId : _creatureRespawnTimesBySpawnId; } - void DeleteRespawnInfo() // delete everything + void UnloadAllRespawnInfos() // delete everything from memory { _respawnTimes.Clear(); _creatureRespawnTimesBySpawnId.Clear(); _gameObjectRespawnTimesBySpawnId.Clear(); } - void DeleteRespawnInfo(RespawnInfo info) + void DeleteRespawnInfo(RespawnInfo info, SQLTransaction dbTrans = null) { // Delete from all relevant containers to ensure consistency Cypher.Assert(info != null); @@ -2532,48 +2530,23 @@ namespace Game.Maps bool removed = GetRespawnMapForType(info.type).Remove(info.spawnId); Cypher.Assert(removed, $"Respawn stores inconsistent for map {GetId()}, spawnid {info.spawnId} (type {info.type})"); - //respawn heap + // respawn heap _respawnTimes.Remove(info); - } - public void RemoveRespawnTime(RespawnInfo info, bool doRespawn = false, SQLTransaction dbTrans = null) - { + // database PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_RESPAWN); stmt.AddValue(0, (ushort)info.type); stmt.AddValue(1, info.spawnId); stmt.AddValue(2, GetId()); stmt.AddValue(3, GetInstanceId()); DB.Characters.ExecuteOrAppend(dbTrans, stmt); - - if (doRespawn) - Respawn(info); - else - DeleteRespawnInfo(info); } - public void RemoveRespawnTime(List respawnData, bool doRespawn, 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 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) + public void RemoveRespawnTime(SpawnObjectType type, ulong spawnId, SQLTransaction dbTrans = null) { RespawnInfo info = GetRespawnInfo(type, spawnId); if (info != null) - RemoveRespawnTime(info, doRespawn, dbTrans); + DeleteRespawnInfo(info, dbTrans); } void ProcessRespawns() @@ -2600,7 +2573,8 @@ namespace Game.Maps else // value changed, update heap position { 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; // 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) @@ -3051,12 +3025,15 @@ namespace Game.Maps 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) { // Delete only - RemoveRespawnTime(type, spawnId, false, dbTrans); + RemoveRespawnTime(type, spawnId, dbTrans); return; } @@ -3067,19 +3044,24 @@ namespace Game.Maps ri.respawnTime = respawnTime; ri.gridId = gridId; ri.zoneId = zoneId; - AddRespawnInfo(ri, replace); + bool success = AddRespawnInfo(ri); - if (writeDB) - SaveRespawnTimeDB(type, spawnId, ri.respawnTime, dbTrans); // might be different from original respawn time if we didn't replace + if (startup) + { + 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 PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.REP_RESPAWN); - stmt.AddValue(0, (ushort)type); - stmt.AddValue(0, spawnId); - stmt.AddValue(1, respawnTime); + stmt.AddValue(0, (ushort)info.type); + stmt.AddValue(0, info.spawnId); + stmt.AddValue(1, info.respawnTime); stmt.AddValue(2, GetId()); stmt.AddValue(3, GetInstanceId()); DB.Characters.ExecuteOrAppend(dbTrans, stmt); @@ -3099,21 +3081,24 @@ namespace Game.Maps var spawnId = result.Read(1); var respawnTime = result.Read(2); - SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId); - if (data != null) - SaveRespawnTime(type, spawnId, data.Id, respawnTime, GetZoneId(PhasingHandler.EmptyPhaseShift, data.spawnPoint), GridDefines.ComputeGridCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY()).GetId(), false); + if (type < SpawnObjectType.Max) + { + SpawnData data = Global.ObjectMgr.GetSpawnData(type, spawnId); + if (data != null) + SaveRespawnTime(type, spawnId, data.Id, respawnTime, GetZoneId(PhasingHandler.EmptyPhaseShift, data.spawnPoint), GridDefines.ComputeGridCoord(data.spawnPoint.GetPositionX(), data.spawnPoint.GetPositionY()).GetId(), null, true); + else + 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}) - spawn does not exist, ignoring"); + Log.outError(LogFilter.Maps, $"Loading saved respawn time of {respawnTime} for spawnid ({type},{spawnId}) - invalid spawn type, ignoring"); } while (result.NextRow()); } } - public long GetRespawnTime(SpawnObjectType type, ulong spawnId) { return (type == SpawnObjectType.GameObject) ? GetGORespawnTime(spawnId) : GetCreatureRespawnTime(spawnId); } - public void DeleteRespawnTimes() { - DeleteRespawnInfo(); + UnloadAllRespawnInfos(); DeleteRespawnTimesInDB(GetId(), GetInstanceId()); } @@ -3754,16 +3739,16 @@ namespace Game.Maps return 0; } - public long GetCreatureRespawnTime(ulong dbGuid) + public long GetRespawnTime(SpawnObjectType type, ulong spawnId) { - return _creatureRespawnTimesBySpawnId.ContainsKey(dbGuid) ? _creatureRespawnTimesBySpawnId[dbGuid].respawnTime : 0; - } - - public long GetGORespawnTime(ulong dbGuid) - { - return _gameObjectRespawnTimesBySpawnId.ContainsKey(dbGuid) ? _gameObjectRespawnTimesBySpawnId[dbGuid].respawnTime : 0; + var respawnDic = GetRespawnMapForType(type); + var respawnInfo = respawnDic.LookupByKey(spawnId); + return (respawnInfo == null) ? 0 : respawnInfo.respawnTime; } + public long GetCreatureRespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.Creature, spawnId); } + public long GetGORespawnTime(ulong spawnId) { return GetRespawnTime(SpawnObjectType.GameObject, spawnId); } + void SetTimer(uint t) { i_gridExpiry = t < MapConst.MinGridDelay ? MapConst.MinGridDelay : t; @@ -3883,7 +3868,15 @@ namespace Game.Maps 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)