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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user