diff --git a/Source/Framework/Database/Databases/CharacterDatabase.cs b/Source/Framework/Database/Databases/CharacterDatabase.cs index 2d70d0c73..451b59f00 100644 --- a/Source/Framework/Database/Databases/CharacterDatabase.cs +++ b/Source/Framework/Database/Databases/CharacterDatabase.cs @@ -589,7 +589,6 @@ namespace Framework.Database PrepareStatement(CharStatements.DEL_CHAR_AURA, "DELETE FROM character_aura WHERE guid = ?"); PrepareStatement(CharStatements.DEL_CHAR_AURA_EFFECT, "DELETE FROM character_aura_effect WHERE guid = ?"); PrepareStatement(CharStatements.DEL_CHAR_GIFT, "DELETE FROM character_gifts WHERE guid = ?"); - PrepareStatement(CharStatements.DEL_CHAR_INSTANCE, "DELETE FROM character_instance_lock WHERE guid = ?"); PrepareStatement(CharStatements.DEL_CHAR_INVENTORY, "DELETE FROM character_inventory WHERE guid = ?"); PrepareStatement(CharStatements.DEL_CHAR_QUESTSTATUS_REWARDED, "DELETE FROM character_queststatus_rewarded WHERE guid = ?"); PrepareStatement(CharStatements.DEL_CHAR_REPUTATION, "DELETE FROM character_reputation WHERE guid = ?"); @@ -745,6 +744,14 @@ namespace Framework.Database // War mode PrepareStatement(CharStatements.SEL_WAR_MODE_TUNING, "SELECT race, COUNT(guid) FROM characters WHERE ((playerFlags & ?) = ?) AND logout_time >= (UNIX_TIMESTAMP() - 604800) GROUP BY race"); + + // Instance locks + PrepareStatement(CharStatements.DEL_CHARACTER_INSTANCE_LOCK, "DELETE FROM character_instance_lock WHERE guid = ? AND mapId = ? AND lockId = ?"); + PrepareStatement(CharStatements.DEL_CHARACTER_INSTANCE_LOCK_BY_GUID, "DELETE FROM character_instance_lock WHERE guid = ?"); + PrepareStatement(CharStatements.INS_CHARACTER_INSTANCE_LOCK, "INSERT INTO character_instance_lock (guid, mapId, lockId, instanceId, difficulty, data, completedEncountersMask, entranceWorldSafeLocId, expiryTime, extended) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); + PrepareStatement(CharStatements.UPD_CHARACTER_INSTANCE_LOCK_EXTENSION, "UPDATE character_instance_lock SET extended = ? WHERE guid = ? AND mapId = ? AND lockId = ?"); + PrepareStatement(CharStatements.DEL_INSTANCE, "DELETE FROM instance WHERE instanceId = ?"); + PrepareStatement(CharStatements.INS_INSTANCE, "INSERT INTO instance (instanceId, data, completedEncountersMask, entranceWorldSafeLocId) VALUES (?, ?, ?, ?)"); } } @@ -1206,7 +1213,6 @@ namespace Framework.Database DEL_CHAR_AURA, DEL_CHAR_AURA_EFFECT, DEL_CHAR_GIFT, - DEL_CHAR_INSTANCE, DEL_CHAR_INVENTORY, DEL_CHAR_QUESTSTATUS_REWARDED, DEL_CHAR_REPUTATION, @@ -1349,6 +1355,13 @@ namespace Framework.Database SEL_WAR_MODE_TUNING, + DEL_CHARACTER_INSTANCE_LOCK, + DEL_CHARACTER_INSTANCE_LOCK_BY_GUID, + INS_CHARACTER_INSTANCE_LOCK, + UPD_CHARACTER_INSTANCE_LOCK_EXTENSION, + DEL_INSTANCE, + INS_INSTANCE, + MAX_CHARACTERDATABASE_STATEMENTS } } diff --git a/Source/Game/Entities/Player/Player.DB.cs b/Source/Game/Entities/Player/Player.DB.cs index 96f687779..e4742fb24 100644 --- a/Source/Game/Entities/Player/Player.DB.cs +++ b/Source/Game/Entities/Player/Player.DB.cs @@ -4029,7 +4029,7 @@ namespace Game.Entities stmt.AddValue(0, guid); trans.Append(stmt); - stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHAR_INSTANCE); + stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_INSTANCE_LOCK_BY_GUID); stmt.AddValue(0, guid); trans.Append(stmt); diff --git a/Source/Game/Maps/Instances/InstanceLockManager.cs b/Source/Game/Maps/Instances/InstanceLockManager.cs index c23641ccd..36f7927cc 100644 --- a/Source/Game/Maps/Instances/InstanceLockManager.cs +++ b/Source/Game/Maps/Instances/InstanceLockManager.cs @@ -89,7 +89,7 @@ namespace Game.Maps if (sharedData == null) { Log.outError(LogFilter.Instance, $"Missing instance data for instance id based lock (id {instanceId})"); - DB.Characters.Query($"DELETE FROM character_instance_lock WHERE instanceId = {instanceId}"); + DB.Characters.Execute($"DELETE FROM character_instance_lock WHERE instanceId = {instanceId}"); continue; } @@ -286,13 +286,24 @@ namespace Game.Maps $"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Expired instance lock for {playerGuid} in instance {updateEvent.InstanceId} is now active"); } - // TODO: DB SAVE IN TRANSACTION - trans.Append($"DELETE FROM character_instance_lock WHERE guid={playerGuid.GetCounter()} AND mapId={entries.MapDifficulty.MapID} AND lockId={entries.MapDifficulty.LockID}"); - string escapedData = instanceLock.GetData().Data; - CharacterDatabase.EscapeString(ref escapedData); - trans.Append($"INSERT INTO character_instance_lock (guid, mapId, lockId, instanceId, difficulty, data, completedEncountersMask, entranceWorldSafeLocId, expiryTime, extended) " + - $"VALUES ({playerGuid.GetCounter()}, {entries.MapDifficulty.MapID}, {entries.MapDifficulty.LockID}, {instanceLock.GetInstanceId()}, {entries.MapDifficulty.DifficultyID}, \"{escapedData}\", " + - $"{instanceLock.GetData().CompletedEncountersMask}, {instanceLock.GetData().EntranceWorldSafeLocId}, {Time.DateTimeToUnixTime(instanceLock.GetExpiryTime())}, {(instanceLock.IsExtended() ? 1 : 0)}"); + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_CHARACTER_INSTANCE_LOCK); + stmt.AddValue(0, playerGuid.GetCounter()); + stmt.AddValue(1, entries.MapDifficulty.MapID); + stmt.AddValue(2, entries.MapDifficulty.LockID); + trans.Append(stmt); + + stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_CHARACTER_INSTANCE_LOCK); + stmt.AddValue(0, playerGuid.GetCounter()); + stmt.AddValue(1, entries.MapDifficulty.MapID); + stmt.AddValue(2, entries.MapDifficulty.LockID); + stmt.AddValue(3, instanceLock.GetInstanceId()); + stmt.AddValue(4, entries.MapDifficulty.DifficultyID); + stmt.AddValue(5, instanceLock.GetData().Data); + stmt.AddValue(6, instanceLock.GetData().CompletedEncountersMask); + stmt.AddValue(7, instanceLock.GetData().EntranceWorldSafeLocId); + stmt.AddValue(8, (ulong)Time.DateTimeToUnixTime(instanceLock.GetExpiryTime())); + stmt.AddValue(9, instanceLock.IsExtended() ? 1 : 0); + trans.Append(stmt); return instanceLock; } @@ -312,10 +323,16 @@ namespace Game.Maps if (updateEvent.EntranceWorldSafeLocId.HasValue) sharedData.EntranceWorldSafeLocId = updateEvent.EntranceWorldSafeLocId.Value; - trans.Append($"DELETE FROM instance2 WHERE instanceId={sharedData.InstanceId}"); - string escapedData = sharedData.Data; - CharacterDatabase.EscapeString(ref escapedData); - trans.Append($"INSERT INTO instance2 (instanceId, data, completedEncountersMask, entranceWorldSafeLocId) VALUES ({sharedData.InstanceId}, \"{escapedData}\", {sharedData.CompletedEncountersMask}, {sharedData.EntranceWorldSafeLocId})"); + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_INSTANCE); + stmt.AddValue(0, sharedData.InstanceId); + trans.Append(stmt); + + stmt = DB.Characters.GetPreparedStatement(CharStatements.INS_INSTANCE); + stmt.AddValue(0, sharedData.InstanceId); + stmt.AddValue(1, sharedData.Data); + stmt.AddValue(2, sharedData.CompletedEncountersMask); + stmt.AddValue(3, sharedData.EntranceWorldSafeLocId); + trans.Append(stmt); } public void OnSharedInstanceLockDataDelete(uint instanceId) @@ -324,7 +341,9 @@ namespace Game.Maps return; _instanceLockDataById.Remove(instanceId); - DB.Characters.Execute($"DELETE FROM instance2 WHERE instanceId={instanceId}"); + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.DEL_INSTANCE); + stmt.AddValue(0, instanceId); + DB.Characters.Execute(stmt); Log.outDebug(LogFilter.Instance, $"Deleting instance {instanceId} as it is no longer referenced by any player"); } @@ -335,7 +354,12 @@ namespace Game.Maps { DateTime oldExpiryTime = instanceLock.GetEffectiveExpiryTime(); instanceLock.SetExtended(extended); - DB.Characters.Execute($"UPDATE character_instance_lock SET extended = {(extended ? 1 : 0)} WHERE guid = {playerGuid.GetCounter()} AND mapId = {entries.MapDifficulty.MapID} AND lockId = {entries.MapDifficulty.LockID}"); + PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_CHARACTER_INSTANCE_LOCK_EXTENSION); + stmt.AddValue(0, extended ? 1 : 0); + stmt.AddValue(1, playerGuid.GetCounter()); + stmt.AddValue(2, entries.MapDifficulty.MapID); + stmt.AddValue(3, entries.MapDifficulty.LockID); + DB.Characters.Execute(stmt); Log.outDebug(LogFilter.Instance, $"[{entries.Map.Id}-{entries.Map.MapName[Global.WorldMgr.GetDefaultDbcLocale()]} | " + $"{entries.MapDifficulty.DifficultyID}-{CliDB.DifficultyStorage.LookupByKey(entries.MapDifficulty.DifficultyID).Name}] Instance lock for {playerGuid} is {(extended ? "now" : "no longer")} extended"); return Tuple.Create(oldExpiryTime, instanceLock.GetEffectiveExpiryTime());