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
+1 -83
View File
@@ -1056,78 +1056,6 @@ namespace Game.Entities
RemoveAtLoginFlag(AtLoginFlags.Resurrect);
}
void _LoadBoundInstances(SQLResult result)
{
m_boundInstances.Clear();
Group group = GetGroup();
if (!result.IsEmpty())
{
do
{
bool perm = result.Read<bool>(1);
uint mapId = result.Read<ushort>(2);
uint instanceId = result.Read<uint>(0);
byte difficulty = result.Read<byte>(3);
BindExtensionState extendState = (BindExtensionState)result.Read<byte>(4);
long resetTime = result.Read<long>(5);
// the resettime for normal instances is only saved when the InstanceSave is unloaded
// so the value read from the DB may be wrong here but only if the InstanceSave is loaded
// and in that case it is not used
uint entranceId = result.Read<uint>(6);
bool deleteInstance = false;
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapId);
string mapname = mapEntry != null ? mapEntry.MapName[Global.WorldMgr.GetDefaultDbcLocale()] : "Unknown";
if (mapEntry == null || !mapEntry.IsDungeon())
{
Log.outError(LogFilter.Player, "_LoadBoundInstances: player {0}({1}) has bind to not existed or not dungeon map {2} ({3})", GetName(), GetGUID().ToString(), mapId, mapname);
deleteInstance = true;
}
else if (CliDB.DifficultyStorage.HasRecord(difficulty))
{
Log.outError(LogFilter.Player, "_LoadBoundInstances: player {0}({1}) has bind to not existed difficulty {2} instance for map {3} ({4})", GetName(), GetGUID().ToString(), difficulty, mapId, mapname);
deleteInstance = true;
}
else
{
MapDifficultyRecord mapDiff = Global.DB2Mgr.GetMapDifficultyData(mapId, (Difficulty)difficulty);
if (mapDiff == null)
{
Log.outError(LogFilter.Player, "_LoadBoundInstances: player {0}({1}) has bind to not existed difficulty {2} instance for map {3} ({4})", GetName(), GetGUID().ToString(), difficulty, mapId, mapname);
deleteInstance = true;
}
else if (!perm && group)
{
Log.outError(LogFilter.Player, "_LoadBoundInstances: player {0}({1}) is in group {2} but has a non-permanent character bind to map {3} ({4}), {5}, {6}",
GetName(), GetGUID().ToString(), group.GetGUID().ToString(), mapId, mapname, instanceId, difficulty);
deleteInstance = true;
}
}
if (deleteInstance)
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, instanceId);
DB.Characters.Execute(stmt);
continue;
}
// since non permanent binds are always solo bind, they can always be reset
InstanceSave save = Global.InstanceSaveMgr.AddInstanceSave(mapId, instanceId, (Difficulty)difficulty, resetTime, entranceId, !perm, true);
if (save != null)
BindToInstance(save, perm, extendState, true);
}
while (result.NextRow());
}
}
void _LoadVoidStorage(SQLResult result)
{
if (result.IsEmpty())
@@ -2793,7 +2721,6 @@ namespace Game.Entities
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.TodayHonorableKills), todayKills);
SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.YesterdayHonorableKills), yesterdayKills);
_LoadBoundInstances(holder.GetResult(PlayerLoginQueryLoad.BoundInstances));
_LoadInstanceTimeRestrictions(holder.GetResult(PlayerLoginQueryLoad.InstanceLockTimes));
_LoadBGData(holder.GetResult(PlayerLoginQueryLoad.BgData));
@@ -2976,15 +2903,6 @@ namespace Game.Entities
Log.outDebug(LogFilter.Player, "Player {0} using client without required expansion tried login at non accessible map {1}", GetName(), mapId);
RelocateToHomebind();
}
// fix crash (because of if (Map* map = _FindMap(instanceId)) in MapInstanced.CreateInstance)
if (instance_id != 0)
{
InstanceSave save = GetInstanceSave(mapId);
if (save != null)
if (save.GetInstanceId() != instance_id)
instance_id = 0;
}
}
// NOW player must have valid map
@@ -3028,7 +2946,7 @@ namespace Game.Entities
areaTrigger = Global.ObjectMgr.GetGoBackTrigger(mapId);
check = true;
}
else if (instance_id != 0 && Global.InstanceSaveMgr.GetInstanceSave(instance_id) == null) // ... and instance is reseted then look for entrance.
else if (instance_id != 0 && Global.InstanceLockMgr.FindActiveInstanceLock(guid, new MapDb2Entries(mapId, map.GetDifficultyID())) != null) // ... and instance is reseted then look for entrance.
{
areaTrigger = Global.ObjectMgr.GetMapEntranceTrigger(mapId);
check = true;
@@ -78,7 +78,6 @@ namespace Game.Entities
bool m_bPassOnGroupLoot;
GroupUpdateCounter[] m_groupUpdateSequences = new GroupUpdateCounter[2];
public Dictionary<Difficulty, Dictionary<uint, InstanceBind>> m_boundInstances = new();
Dictionary<uint, uint> m_recentInstances = new();
Dictionary<uint, long> _instanceResetTimes = new();
uint _pendingBindId;
+1 -221
View File
@@ -290,152 +290,6 @@ namespace Game.Entities
public ZonePVPTypeOverride GetOverrideZonePVPType() { return (ZonePVPTypeOverride)(uint)m_activePlayerData.OverrideZonePVPType; }
public void SetOverrideZonePVPType(ZonePVPTypeOverride type) { SetUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OverrideZonePVPType), (uint)type); }
public InstanceBind GetBoundInstance(uint mapid, Difficulty difficulty, bool withExpired = false)
{
// some instances only have one difficulty
MapDifficultyRecord mapDiff = Global.DB2Mgr.GetDownscaledMapDifficultyData(mapid, ref difficulty);
if (mapDiff == null)
return null;
var difficultyDic = m_boundInstances.LookupByKey(difficulty);
if (difficultyDic == null)
return null;
var instanceBind = difficultyDic.LookupByKey(mapid);
if (instanceBind != null)
if (instanceBind.extendState != 0 || withExpired)
return instanceBind;
return null;
}
public Dictionary<uint, InstanceBind> GetBoundInstances(Difficulty difficulty) { return m_boundInstances.LookupByKey(difficulty); }
public InstanceSave GetInstanceSave(uint mapid)
{
MapRecord mapEntry = CliDB.MapStorage.LookupByKey(mapid);
InstanceBind pBind = GetBoundInstance(mapid, GetDifficultyID(mapEntry));
InstanceSave pSave = pBind?.save;
if (pBind == null || !pBind.perm)
{
Group group = GetGroup();
if (group)
{
InstanceBind groupBind = group.GetBoundInstance(GetDifficultyID(mapEntry), mapid);
if (groupBind != null)
pSave = groupBind.save;
}
}
return pSave;
}
public void UnbindInstance(uint mapid, Difficulty difficulty, bool unload = false)
{
var difficultyDic = m_boundInstances.LookupByKey(difficulty);
if (difficultyDic != null)
{
var pair = difficultyDic.Find(mapid);
if (pair.Value != null)
UnbindInstance(pair, difficultyDic, unload);
}
}
public void UnbindInstance(KeyValuePair<uint, InstanceBind> pair, Dictionary<uint, InstanceBind> difficultyDic, bool unload)
{
if (pair.Value != null)
{
if (!unload)
{
PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_INSTANCE_BY_INSTANCE_GUID);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, pair.Value.save.GetInstanceId());
DB.Characters.Execute(stmt);
}
if (pair.Value.perm)
GetSession().SendCalendarRaidLockoutRemoved(pair.Value.save);
pair.Value.save.RemovePlayer(this); // save can become invalid
difficultyDic.Remove(pair.Key);
}
}
public InstanceBind BindToInstance(InstanceSave save, bool permanent, BindExtensionState extendState = BindExtensionState.Normal, bool load = false)
{
if (save != null)
{
InstanceBind bind = new();
if (m_boundInstances.ContainsKey(save.GetDifficultyID()) && m_boundInstances[save.GetDifficultyID()].ContainsKey(save.GetMapId()))
bind = m_boundInstances[save.GetDifficultyID()][save.GetMapId()];
if (extendState == BindExtensionState.Keep) // special flag, keep the player's current extend state when updating for new boss down
{
if (save == bind.save)
extendState = bind.extendState;
else
extendState = BindExtensionState.Normal;
}
if (!load)
{
PreparedStatement stmt;
if (bind.save != null)
{
// update the save when the group kills a boss
if (permanent != bind.perm || save != bind.save || extendState != bind.extendState)
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_CHAR_INSTANCE);
stmt.AddValue(0, save.GetInstanceId());
stmt.AddValue(1, permanent);
stmt.AddValue(2, (byte)extendState);
stmt.AddValue(3, GetGUID().GetCounter());
stmt.AddValue(4, bind.save.GetInstanceId());
DB.Characters.Execute(stmt);
}
}
else
{
stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHAR_INSTANCE);
stmt.AddValue(0, GetGUID().GetCounter());
stmt.AddValue(1, save.GetInstanceId());
stmt.AddValue(2, permanent);
stmt.AddValue(3, (byte)extendState);
DB.Characters.Execute(stmt);
}
}
if (bind.save != save)
{
if (bind.save != null)
bind.save.RemovePlayer(this);
save.AddPlayer(this);
}
if (permanent)
save.SetCanReset(false);
bind.save = save;
bind.perm = permanent;
bind.extendState = extendState;
if (!load)
Log.outDebug(LogFilter.Maps, "Player.BindToInstance: Player '{0}' ({1}) is now bound to map (ID: {2}, Instance {3}, Difficulty {4})", GetName(), GetGUID().ToString(), save.GetMapId(), save.GetInstanceId(), save.GetDifficultyID());
Global.ScriptMgr.OnPlayerBindToInstance(this, save.GetDifficultyID(), save.GetMapId(), permanent, extendState);
if (!m_boundInstances.ContainsKey(save.GetDifficultyID()))
m_boundInstances[save.GetDifficultyID()] = new Dictionary<uint, InstanceBind>();
m_boundInstances[save.GetDifficultyID()][save.GetMapId()] = bind;
return bind;
}
return null;
}
public void ConfirmPendingBind()
{
InstanceMap map = GetMap().ToInstanceMap();
@@ -466,7 +320,7 @@ namespace Game.Entities
lockInfos.InstanceID = instanceLock.GetInstanceId();
lockInfos.MapID = instanceLock.GetMapId();
lockInfos.DifficultyID = (uint)instanceLock.GetDifficultyId();
lockInfos.TimeRemaining = (int)(instanceLock.GetEffectiveExpiryTime() - now).TotalSeconds;
lockInfos.TimeRemaining = (int)Math.Max((instanceLock.GetEffectiveExpiryTime() - now).TotalSeconds, 0);
lockInfos.CompletedMask = instanceLock.GetData().CompletedEncountersMask;
lockInfos.Locked = !instanceLock.IsExpired();
@@ -646,52 +500,7 @@ namespace Game.Entities
// Reset all solo instances and optionally send a message on success for each
public void ResetInstances(InstanceResetMethod method, bool isRaid, bool isLegacy)
{
// method can be INSTANCE_RESET_ALL, INSTANCE_RESET_CHANGE_DIFFICULTY, INSTANCE_RESET_GROUP_JOIN
// we assume that when the difficulty changes, all instances that can be reset will be
Difficulty difficulty = GetDungeonDifficultyID();
if (isRaid)
{
if (!isLegacy)
difficulty = GetRaidDifficultyID();
else
difficulty = GetLegacyRaidDifficultyID();
}
var difficultyDic = m_boundInstances.LookupByKey(difficulty);
if (difficultyDic == null)
return;
foreach (var pair in difficultyDic)
{
InstanceSave p = pair.Value.save;
MapRecord entry = CliDB.MapStorage.LookupByKey(difficulty);
if (entry == null || entry.IsRaid() != isRaid || !p.CanReset())
continue;
if (method == InstanceResetMethod.All)
{
// the "reset all instances" method can only reset normal maps
if (entry.InstanceType == MapTypes.Raid || difficulty == Difficulty.Heroic)
continue;
}
// if the map is loaded, reset it
Map map = Global.MapMgr.FindMap(p.GetMapId(), p.GetInstanceId());
if (map != null && map.IsDungeon())
if (!map.ToInstanceMap().Reset(method))
continue;
// since this is a solo instance there should not be any players inside
if (method == InstanceResetMethod.All || method == InstanceResetMethod.ChangeDifficulty)
SendResetInstanceSuccess(p.GetMapId());
p.DeleteFromDB();
difficultyDic.Remove(pair.Key);
// the following should remove the instance save from the manager and delete it as well
p.RemovePlayer(this);
}
}
public void SendResetInstanceSuccess(uint MapId)
@@ -719,35 +528,6 @@ namespace Game.Entities
SendPacket(transferAborted);
}
public void SendInstanceResetWarning(uint mapid, Difficulty difficulty, uint time, bool welcome)
{
// type of warning, based on the time remaining until reset
InstanceResetWarningType type;
if (welcome)
type = InstanceResetWarningType.Welcome;
else if (time > 21600)
type = InstanceResetWarningType.Welcome;
else if (time > 3600)
type = InstanceResetWarningType.WarningHours;
else if (time > 300)
type = InstanceResetWarningType.WarningMin;
else
type = InstanceResetWarningType.WarningMinSoon;
RaidInstanceMessage raidInstanceMessage = new();
raidInstanceMessage.Type = type;
raidInstanceMessage.MapID = mapid;
raidInstanceMessage.DifficultyID = difficulty;
InstanceBind bind = GetBoundInstance(mapid, difficulty);
if (bind != null)
raidInstanceMessage.Locked = bind.perm;
else
raidInstanceMessage.Locked = false;
raidInstanceMessage.Extended = false;
SendPacket(raidInstanceMessage);
}
public override void ProcessTerrainStatusUpdate(ZLiquidStatus oldLiquidStatus, LiquidData newLiquidData)
{
// process liquid auras using generic unit code
-5
View File
@@ -727,11 +727,6 @@ namespace Game.Entities
if (GetTransport() != null)
GetTransport().RemovePassenger(this);
// clean up player-instance binds, may unload some instance saves
foreach (var difficultyDic in m_boundInstances.Values)
foreach (var instanceBind in difficultyDic.Values)
instanceBind.save.RemovePlayer(this);
}
public override void AddToWorld()