Core/Instances: Delete InstanceSaveMgr and replace most of its uses with new InstanceLockMgr

Port From (https://github.com/TrinityCore/TrinityCore/commit/9b924522d0549dd67b10e2cbdfc20297dd21e182)
This commit is contained in:
hondacrx
2022-10-04 10:57:04 -04:00
parent 793cf91a24
commit 66c7047a29
27 changed files with 186 additions and 1545 deletions
-211
View File
@@ -673,26 +673,6 @@ namespace Game.Groups
PreparedStatement stmt;
SQLTransaction trans = new();
// Remove the groups permanent instance bindings
foreach (var difficultyDic in m_boundInstances.Values)
{
foreach (var pair in difficultyDic.ToList())
{
// Do not unbind saves of instances that already had map created (a newLeader entered)
// forcing a new instance with another leader requires group disbanding (confirmed on retail)
if (pair.Value.perm && Global.MapMgr.FindMap(pair.Key, pair.Value.save.GetInstanceId()) == null)
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_GROUP_INSTANCE_PERM_BINDING);
stmt.AddValue(0, m_dbStoreId);
stmt.AddValue(1, pair.Value.save.GetInstanceId());
trans.Append(stmt);
pair.Value.save.RemoveGroup(this);
difficultyDic.Remove(pair.Key);
}
}
}
// Update the group leader
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_GROUP_LEADER);
@@ -1381,166 +1361,7 @@ namespace Game.Groups
public void ResetInstances(InstanceResetMethod method, bool isRaid, bool isLegacy, Player SendMsgTo)
{
if (IsBGGroup() || IsBFGroup())
return;
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_DISBAND
// we assume that when the difficulty changes, all instances that can be reset will be
Difficulty diff = GetDungeonDifficultyID();
if (isRaid)
{
if (!isLegacy)
diff = GetRaidDifficultyID();
else
diff = GetLegacyRaidDifficultyID();
}
var difficultyDic = m_boundInstances.LookupByKey(diff);
if (difficultyDic == null)
return;
foreach (var pair in difficultyDic.ToList())
{
InstanceSave instanceSave = pair.Value.save;
MapRecord entry = CliDB.MapStorage.LookupByKey(pair.Key);
if (entry == null || entry.IsRaid() != isRaid || (!instanceSave.CanReset() && method != InstanceResetMethod.GroupDisband))
continue;
if (method == InstanceResetMethod.All)
{
// the "reset all instances" method can only reset normal maps
if (entry.InstanceType == MapTypes.Raid || diff == Difficulty.Heroic)
continue;
}
bool isEmpty = true;
// if the map is loaded, reset it
Map map = Global.MapMgr.FindMap(instanceSave.GetMapId(), instanceSave.GetInstanceId());
if (map && map.IsDungeon() && !(method == InstanceResetMethod.GroupDisband && !instanceSave.CanReset()))
{
if (instanceSave.CanReset())
isEmpty = ((InstanceMap)map).Reset(method);
else
isEmpty = !map.HavePlayers();
}
if (SendMsgTo)
{
if (!isEmpty)
SendMsgTo.SendResetInstanceFailed(ResetFailedReason.Failed, instanceSave.GetMapId());
else if (WorldConfig.GetBoolValue(WorldCfg.InstancesResetAnnounce))
{
Group group = SendMsgTo.GetGroup();
if (group)
{
for (GroupReference refe = group.GetFirstMember(); refe != null; refe = refe.Next())
{
Player player = refe.GetSource();
if (player)
player.SendResetInstanceSuccess(instanceSave.GetMapId());
}
}
else
SendMsgTo.SendResetInstanceSuccess(instanceSave.GetMapId());
}
else
SendMsgTo.SendResetInstanceSuccess(instanceSave.GetMapId());
}
if (isEmpty || method == InstanceResetMethod.GroupDisband || method == InstanceResetMethod.ChangeDifficulty)
{
// do not reset the instance, just unbind if others are permanently bound to it
if (instanceSave.CanReset())
{
if (map != null && map.IsDungeon() && SendMsgTo)
{
AreaTriggerStruct instanceEntrance = Global.ObjectMgr.GetGoBackTrigger(map.GetId());
if (instanceEntrance == null)
Log.outDebug(LogFilter.Misc, $"Instance entrance not found for map {map.GetId()}");
else
{
WorldSafeLocsEntry graveyardLocation = Global.ObjectMgr.GetClosestGraveYard(
new WorldLocation(instanceEntrance.target_mapId, instanceEntrance.target_X, instanceEntrance.target_Y, instanceEntrance.target_Z),
SendMsgTo.GetTeam(), null);
uint zoneId = Global.TerrainMgr.GetZoneId(PhasingHandler.EmptyPhaseShift, graveyardLocation.Loc.GetMapId(),
graveyardLocation.Loc.GetPositionX(), graveyardLocation.Loc.GetPositionY(), graveyardLocation.Loc.GetPositionZ());
foreach (MemberSlot member in GetMemberSlots())
{
if (!Global.ObjAccessor.FindConnectedPlayer(member.guid))
{
var stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_CHARACTER_POSITION_BY_MAPID);
stmt.AddValue(0, graveyardLocation.Loc.GetPositionX());
stmt.AddValue(1, graveyardLocation.Loc.GetPositionY());
stmt.AddValue(2, graveyardLocation.Loc.GetPositionZ());
stmt.AddValue(3, instanceEntrance.target_Orientation);
stmt.AddValue(4, graveyardLocation.Loc.GetMapId());
stmt.AddValue(5, zoneId);
stmt.AddValue(6, member.guid.GetCounter());
stmt.AddValue(7, map.GetId());
DB.Characters.Execute(stmt);
}
}
}
}
instanceSave.DeleteFromDB();
}
else
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_GROUP_INSTANCE_BY_INSTANCE);
stmt.AddValue(0, instanceSave.GetInstanceId());
DB.Characters.Execute(stmt);
}
difficultyDic.Remove(pair.Key);
// this unloads the instance save unless online players are bound to it
// (eg. permanent binds or GM solo binds)
instanceSave.RemoveGroup(this);
}
}
}
public InstanceBind GetBoundInstance(Player player)
{
uint mapid = player.GetMapId();
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapid);
return GetBoundInstance(mapEntry);
}
public InstanceBind GetBoundInstance(Map aMap)
{
return GetBoundInstance(aMap.GetEntry());
}
public InstanceBind GetBoundInstance(MapRecord mapEntry)
{
if (mapEntry == null || !mapEntry.IsDungeon())
return null;
Difficulty difficulty = GetDifficultyID(mapEntry);
return GetBoundInstance(difficulty, mapEntry.Id);
}
public InstanceBind GetBoundInstance(Difficulty difficulty, uint mapId)
{
// some instances only have one difficulty
Global.DB2Mgr.GetDownscaledMapDifficultyData(mapId, ref difficulty);
var difficultyDic = m_boundInstances.LookupByKey(difficulty);
if (difficultyDic == null)
return null;
var instanceBind = difficultyDic.LookupByKey(mapId);
if (instanceBind != null)
return instanceBind;
return null;
}
public void LinkOwnedInstance(GroupInstanceReference refe)
@@ -1548,30 +1369,6 @@ namespace Game.Groups
m_ownedInstancesMgr.InsertLast(refe);
}
public void UnbindInstance(uint mapid, Difficulty difficulty, bool unload = false)
{
var difficultyDic = m_boundInstances.LookupByKey(difficulty);
if (difficultyDic == null)
return;
var instanceBind = difficultyDic.LookupByKey(mapid);
if (instanceBind != null)
{
if (!unload)
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_GROUP_INSTANCE_BY_GUID);
stmt.AddValue(0, m_dbStoreId);
stmt.AddValue(1, instanceBind.save.GetInstanceId());
DB.Characters.Execute(stmt);
}
instanceBind.save.RemoveGroup(this); // save can become invalid
difficultyDic.Remove(mapid);
}
}
void _homebindIfInstance(Player player)
{
if (player && !player.IsGameMaster() && CliDB.MapStorage.LookupByKey(player.GetMapId()).IsDungeon())
@@ -1986,11 +1783,6 @@ namespace Game.Groups
}
}
public Dictionary<uint, InstanceBind> GetBoundInstances(Difficulty difficulty)
{
return m_boundInstances.LookupByKey(difficulty);
}
void _initRaidSubGroupsCounter()
{
// Sub group counters initialization
@@ -2077,8 +1869,6 @@ namespace Game.Groups
worker(refe.GetSource());
}
uint GetInstanceId(MapRecord mapEntry) { return 0; }
public ObjectGuid GetRecentInstanceOwner(uint mapId)
{
@@ -2119,7 +1909,6 @@ namespace Game.Groups
ItemQuality m_lootThreshold;
ObjectGuid m_looterGuid;
ObjectGuid m_masterLooterGuid;
Dictionary<Difficulty, Dictionary<uint, InstanceBind>> m_boundInstances = new();
Dictionary<uint, Tuple<ObjectGuid, uint>> m_recentInstances = new();
GroupInstanceRefManager m_ownedInstancesMgr = new();
byte[] m_subGroupsCounts;
-43
View File
@@ -182,49 +182,6 @@ namespace Game.Groups
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} group members in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
}
Log.outInfo(LogFilter.ServerLoading, "Loading Group instance saves...");
{
uint oldMSTime = Time.GetMSTime();
// 0 1 2 3 4 5 6
SQLResult result = DB.Characters.Query("SELECT gi.guid, i.map, gi.instance, gi.permanent, i.difficulty, i.resettime, i.entranceId, " +
// 7
"(SELECT COUNT(1) FROM character_instance ci LEFT JOIN `groups` g ON ci.guid = g.leaderGuid WHERE ci.instance = gi.instance AND ci.permanent = 1 LIMIT 1) " +
"FROM group_instance gi LEFT JOIN instance i ON gi.instance = i.id ORDER BY guid");
if (result.IsEmpty())
{
Log.outInfo(LogFilter.ServerLoading, "Loaded 0 group-instance saves. DB table `group_instance` is empty!");
return;
}
uint count = 0;
do
{
Group group = GetGroupByDbStoreId(result.Read<uint>(0));
// group will never be NULL (we have run consistency sql's before loading)
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(result.Read<ushort>(1));
if (mapEntry == null || !mapEntry.IsDungeon())
{
Log.outError(LogFilter.Sql, "Incorrect entry in group_instance table : no dungeon map {0}", result.Read<ushort>(1));
continue;
}
uint diff = result.Read<byte>(4);
DifficultyRecord difficultyEntry = CliDB.DifficultyStorage.LookupByKey(diff);
if (difficultyEntry == null || difficultyEntry.InstanceType != mapEntry.InstanceType)
continue;
InstanceSave save = Global.InstanceSaveMgr.AddInstanceSave(mapEntry.Id, result.Read<uint>(2), (Difficulty)diff, result.Read<long>(5), result.Read<uint>(6), result.Read<ulong>(7) == 0, true);
group.BindToInstance(save, result.Read<bool>(3), true);
++count;
}
while (result.NextRow());
Log.outInfo(LogFilter.ServerLoading, "Loaded {0} group-instance saves in {1} ms", count, Time.GetMSTimeDiffToNow(oldMSTime));
}
}
Dictionary<ulong, Group> GroupStore = new();