From 67d6fa48eb601995b95e2d56382698c43c954119 Mon Sep 17 00:00:00 2001 From: hondacrx Date: Tue, 4 Oct 2022 14:04:16 -0400 Subject: [PATCH] Core/Scripts: Save instance data in JSON format Port From (https://github.com/TrinityCore/TrinityCore/commit/76be303351ae398b7f9e69e4c472cb5b05fce45e) --- Source/Game/Chat/Commands/InstanceCommands.cs | 6 +- .../Maps/Instances/InstanceLockManager.cs | 4 +- Source/Game/Maps/Instances/InstanceScript.cs | 202 +++++++------ .../Game/Maps/Instances/InstanceScriptData.cs | 279 ++++++++++++++++++ Source/Game/Maps/Map.cs | 52 +++- .../InstanceBlackrockDepths.cs | 75 +---- .../MoltenCore/InstanceMoltenCore.cs | 2 +- 7 files changed, 454 insertions(+), 166 deletions(-) create mode 100644 Source/Game/Maps/Instances/InstanceScriptData.cs diff --git a/Source/Game/Chat/Commands/InstanceCommands.cs b/Source/Game/Chat/Commands/InstanceCommands.cs index 52f7fa450..86328c31a 100644 --- a/Source/Game/Chat/Commands/InstanceCommands.cs +++ b/Source/Game/Chat/Commands/InstanceCommands.cs @@ -116,9 +116,9 @@ namespace Game.Chat } [Command("savedata", RBACPermissions.CommandInstanceSavedata)] - static bool HandleInstanceSaveData(CommandHandler handler) + static bool HandleInstanceSaveDataCommand(CommandHandler handler) { - Player player = handler.GetSession().GetPlayer(); + /*Player player = handler.GetSession().GetPlayer(); InstanceMap map = player.GetMap().ToInstanceMap(); if (map == null) { @@ -132,7 +132,7 @@ namespace Game.Chat return false; } - map.GetInstanceScript().SaveToDB(); + map.GetInstanceScript().SaveToDB();*/ return true; } diff --git a/Source/Game/Maps/Instances/InstanceLockManager.cs b/Source/Game/Maps/Instances/InstanceLockManager.cs index 13ff7ce5c..5e13ce427 100644 --- a/Source/Game/Maps/Instances/InstanceLockManager.cs +++ b/Source/Game/Maps/Instances/InstanceLockManager.cs @@ -460,13 +460,13 @@ namespace Game.Maps _sharedData = sharedData; } - public void SetInstanceId(uint instanceId) + public override void SetInstanceId(uint instanceId) { base.SetInstanceId(instanceId); _sharedData.InstanceId = instanceId; } - public InstanceLockData GetInstanceInitializationData() { return _sharedData; } + public override InstanceLockData GetInstanceInitializationData() { return _sharedData; } public SharedInstanceLockData GetSharedData() { return _sharedData; } } diff --git a/Source/Game/Maps/Instances/InstanceScript.cs b/Source/Game/Maps/Instances/InstanceScript.cs index 6342cd55e..c529eaf42 100644 --- a/Source/Game/Maps/Instances/InstanceScript.cs +++ b/Source/Game/Maps/Instances/InstanceScript.cs @@ -44,17 +44,6 @@ namespace Game.Maps InstanceScenario scenario = instance.GetInstanceScenario(); if (scenario != null) scenario.SaveToDB(); - - string data = GetSaveData(); - if (string.IsNullOrEmpty(data)) - return; - - PreparedStatement stmt = DB.Characters.GetPreparedStatement(CharStatements.UPD_INSTANCE_DATA); - stmt.AddValue(0, GetCompletedEncounterMask()); - stmt.AddValue(1, data); - stmt.AddValue(2, _entranceId); - stmt.AddValue(3, instance.GetInstanceId()); - DB.Characters.Execute(stmt); } public virtual bool IsEncounterInProgress() @@ -104,9 +93,7 @@ namespace Game.Maps public void SetHeaders(string dataHeaders) { - foreach (char header in dataHeaders) - if (char.IsLetter(header)) - headers.Add(header); + headers = dataHeaders; } public void LoadBossBoundaries(BossBoundaryEntry[] data) @@ -178,7 +165,7 @@ namespace Game.Maps for (int i = 0; i < MapConst.MaxDungeonEncountersPerBoss; ++i) bosses[bossId].DungeonEncounters[i] = CliDB.DungeonEncounterStorage.LookupByKey(dungeonEncounterIds[i]); } - + public virtual void UpdateDoorState(GameObject door) { var range = doors.LookupByKey(door.GetEntry()); @@ -430,8 +417,8 @@ namespace Game.Maps bossInfo.state = state; SaveToDB(); - if (state == EncounterState.Done && dungeonEncounter != null) - instance.UpdateInstanceLock(dungeonEncounter, new(id, state)); + if (dungeonEncounter != null) + instance.UpdateInstanceLock(new UpdateBossStateSaveDataEvent(dungeonEncounter, id, state)); } for (uint type = 0; type < (int)DoorType.Max; ++type) @@ -470,7 +457,7 @@ namespace Game.Maps UpdateSpawnGroups(); } - public virtual void Load(string data) + public void Load(string data) { if (string.IsNullOrEmpty(data)) { @@ -480,12 +467,11 @@ namespace Game.Maps OutLoadInstData(data); - var loadStream = new StringArguments(data); - - if (ReadSaveDataHeaders(loadStream)) + InstanceScriptDataReader reader = new(this); + if (reader.Load(data) == InstanceScriptDataReader.Result.Ok) { - ReadSaveDataBossStates(loadStream); - ReadSaveDataMore(loadStream); + UpdateSpawnGroups(); + AfterDataLoad(); } else OutLoadInstDataFail(); @@ -493,84 +479,39 @@ namespace Game.Maps OutLoadInstDataComplete(); } - bool ReadSaveDataHeaders(StringArguments data) - { - foreach (char header in headers) - { - char buff = data.NextChar(); - - if (header != buff) - return false; - } - - return true; - } - - void ReadSaveDataBossStates(StringArguments data) - { - foreach (var pair in bosses) - { - EncounterState buff = (EncounterState)data.NextUInt32(); - if (buff == EncounterState.InProgress || buff == EncounterState.Fail || buff == EncounterState.Special) - buff = EncounterState.NotStarted; - - if (buff < EncounterState.ToBeDecided) - SetBossState(pair.Key, buff); - } - UpdateSpawnGroups(); - } - - public virtual string GetSaveData() + public string GetSaveData() { OutSaveInstData(); - StringBuilder saveStream = new(); + InstanceScriptDataWriter writer = new(this); - WriteSaveDataHeaders(saveStream); - WriteSaveDataBossStates(saveStream); - WriteSaveDataMore(saveStream); + writer.FillData(); OutSaveInstDataComplete(); - return saveStream.ToString(); + return writer.GetString(); } - public string UpdateSaveData(string oldData, UpdateSaveDataEvent saveEvent) + public string UpdateBossStateSaveData(string oldData, UpdateBossStateSaveDataEvent saveEvent) { if (!instance.GetMapDifficulty().IsUsingEncounterLocks()) return GetSaveData(); - int position = (int)(headers.Count + saveEvent.BossId) * 2; - StringBuilder newData = new(oldData); - if (position >= oldData.Length) - { - // Initialize blank data - StringBuilder saveStream = new(); - WriteSaveDataHeaders(saveStream); - for (var i = 0; i < bosses.Count; ++i) - saveStream.Append($"{(uint)EncounterState.NotStarted} "); - - WriteSaveDataMore(saveStream); - - newData = saveStream; - } - - newData.Remove(position, 2); - newData.Insert(position, $"{(uint)saveEvent.NewState}0"); - - return newData.ToString(); - } - - void WriteSaveDataHeaders(StringBuilder data) - { - foreach (char header in headers) - data.AppendFormat("{0} ", header); + InstanceScriptDataWriter writer = new(this); + writer.FillDataFrom(oldData); + writer.SetBossState(saveEvent); + return writer.GetString(); } - void WriteSaveDataBossStates(StringBuilder data) + public string UpdateAdditionalSaveData(string oldData, UpdateAdditionalSaveDataEvent saveEvent) { - foreach (BossInfo bossInfo in bosses.Values) - data.AppendFormat("{0} ", (uint)bossInfo.state); + if (!instance.GetMapDifficulty().IsUsingEncounterLocks()) + return GetSaveData(); + + InstanceScriptDataWriter writer = new(this); + writer.FillDataFrom(oldData); + writer.SetAdditionalData(saveEvent); + return writer.GetString(); } public void HandleGameObject(ObjectGuid guid, bool open, GameObject go = null) @@ -763,7 +704,7 @@ namespace Game.Maps return false; } - + public void SetEntranceLocation(uint worldSafeLocationId) { _entranceId = worldSafeLocationId; @@ -998,6 +939,12 @@ namespace Game.Maps public byte GetCombatResurrectionCharges() { return _combatResurrectionCharges; } + public void RegisterPersistentScriptValue(PersistentInstanceScriptValueBase value) { _persistentScriptValues.Add(value); } + + public string GetHeader() { return headers; } + + public List GetPersistentScriptValues() { return _persistentScriptValues; } + public void SetBossNumber(uint number) { for (uint i = 0; i < number; ++i) @@ -1010,15 +957,15 @@ namespace Game.Maps public void OutLoadInstDataComplete() { Log.outDebug(LogFilter.Scripts, "Instance Data Load for Instance {0} (Map {1}, Instance Id: {2}) is complete.", instance.GetMapName(), instance.GetId(), instance.GetInstanceId()); } public void OutLoadInstDataFail() { Log.outDebug(LogFilter.Scripts, "Unable to load Instance Data for Instance {0} (Map {1}, Instance Id: {2}).", instance.GetMapName(), instance.GetId(), instance.GetInstanceId()); } - public virtual void ReadSaveDataMore(StringArguments data) { } - - public virtual void WriteSaveDataMore(StringBuilder data) { } - public List GetInstanceSpawnGroups() { return _instanceSpawnGroups; } + // Override this function to validate all additional data loads + public virtual void AfterDataLoad() { } + public InstanceMap instance; - List headers = new(); + string headers; Dictionary bosses = new(); + List _persistentScriptValues = new(); MultiMap doors = new(); Dictionary minions = new(); Dictionary _creatureInfo = new(); @@ -1131,15 +1078,84 @@ namespace Game.Maps public BossInfo bossInfo; } - public struct UpdateSaveDataEvent + public struct UpdateBossStateSaveDataEvent { + public DungeonEncounterRecord DungeonEncounter; public uint BossId; public EncounterState NewState; - public UpdateSaveDataEvent(uint bossId, EncounterState state) + public UpdateBossStateSaveDataEvent(DungeonEncounterRecord dungeonEncounter, uint bossId, EncounterState state) { + DungeonEncounter = dungeonEncounter; BossId = bossId; NewState = state; } } + + public struct UpdateAdditionalSaveDataEvent + { + public string Key; + public object Value; + + public UpdateAdditionalSaveDataEvent(string key, object value) + { + Key = key; + Value = value; + } + } + + public class PersistentInstanceScriptValueBase + { + protected InstanceScript _instance; + protected string _name; + protected object _value; + + protected PersistentInstanceScriptValueBase(InstanceScript instance, string name, object value) + { + _instance = instance; + _name = name; + _value = value; + + _instance.RegisterPersistentScriptValue(this); + } + + public string GetName() { return _name; } + + public UpdateAdditionalSaveDataEvent CreateEvent() + { + return new UpdateAdditionalSaveDataEvent(_name, _value); + } + + public void LoadValue(long value) + { + _value = value; + } + + public void LoadValue(double value) + { + _value = value; + } + } + + class PersistentInstanceScriptValue : PersistentInstanceScriptValueBase + { + public PersistentInstanceScriptValue(InstanceScript instance, string name, T value) : base(instance, name, value) { } + + public PersistentInstanceScriptValue SetValue(T value) + { + _value = value; + NotifyValueChanged(); + return this; + } + + void NotifyValueChanged() + { + _instance.instance.UpdateInstanceLock(CreateEvent()); + } + + void LoadValue(T value) + { + _value = value; + } + } } diff --git a/Source/Game/Maps/Instances/InstanceScriptData.cs b/Source/Game/Maps/Instances/InstanceScriptData.cs new file mode 100644 index 000000000..aa6bfeea3 --- /dev/null +++ b/Source/Game/Maps/Instances/InstanceScriptData.cs @@ -0,0 +1,279 @@ +/* + * Copyright (C) 2012-2020 CypherCore + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +using Framework.Constants; +using Game.DataStorage; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Text.Json; +using System.Text.Json.Nodes; + +namespace Game.Maps +{ + class InstanceScriptDataReader + { + public enum Result + { + Ok, + MalformedJson, + RootIsNotAnObject, + MissingHeader, + UnexpectedHeader, + MissingBossStates, + BossStatesIsNotAnObject, + UnknownBoss, + BossStateIsNotAnObject, + MissingBossState, + BossStateValueIsNotANumber, + AdditionalDataIsNotAnObject, + AdditionalDataUnexpectedValueType + } + + InstanceScript _instance; + JsonDocument _doc; + + public InstanceScriptDataReader(InstanceScript instance) + { + _instance = instance; + } + + public Result Load(string data) + { + /* + Expected JSON + + { + "Header": "HEADER_STRING_SET_BY_SCRIPT", + "BossStates": [0,2,0,...] // indexes are boss ids, values are EncounterState + "AdditionalData: { // optional + "ExtraKey1": 123 + "AnotherExtraKey": 2.0 + } + } + */ + + try + { + _doc = JsonDocument.Parse(data); + } + catch (JsonException ex) + { + Log.outError(LogFilter.Scripts, $"JSON parser error {ex.Message} at {ex.LineNumber} while loading data for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.MalformedJson; + } + + if (_doc.RootElement.ValueKind != JsonValueKind.Object) + { + Log.outError(LogFilter.Scripts, $"Root JSON value is not an object for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.RootIsNotAnObject; + } + + Result result = ParseHeader(); + if (result != Result.Ok) + return result; + + result = ParseBossStates(); + if (result != Result.Ok) + return result; + + result = ParseAdditionalData(); + if (result != Result.Ok) + return result; + + return Result.Ok; + } + + Result ParseHeader() + { + if (!_doc.RootElement.TryGetProperty("Header", out JsonElement header)) + { + Log.outError(LogFilter.Scripts, $"Missing data header for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.MissingHeader; + } + + if (header.GetString() != _instance.GetHeader()) + { + Log.outError(LogFilter.Scripts, $"Incorrect data header for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}], expected \"{_instance.GetHeader()}\" got \"{header.GetString()}\""); + return Result.UnexpectedHeader; + } + + return Result.Ok; + } + + Result ParseBossStates() + { + if (!_doc.RootElement.TryGetProperty("BossStates", out JsonElement bossStates)) + { + Log.outError(LogFilter.Scripts, $"Missing boss states for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.MissingBossStates; + } + + if (bossStates.ValueKind != JsonValueKind.Array) + { + Log.outError(LogFilter.Scripts, $"Boss states is not an array for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.BossStatesIsNotAnObject; + } + + for (int bossId = 0; bossId < bossStates.GetArrayLength(); ++bossId) + { + if (bossId >= _instance.GetEncounterCount()) + { + Log.outError(LogFilter.Scripts, $"Boss states has entry for boss with higher id ({bossId}) than number of bosses ({_instance.GetEncounterCount()}) for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.UnknownBoss; + } + + var bossState = bossStates[bossId]; + if (bossState.ValueKind != JsonValueKind.Number) + { + Log.outError(LogFilter.Scripts, $"Boss state for boss ({bossId}) is not a number for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.BossStateIsNotAnObject; + } + + EncounterState state = (EncounterState)bossState.GetInt32(); + if (state == EncounterState.InProgress || state == EncounterState.Fail || state == EncounterState.Special) + state = EncounterState.NotStarted; + + if (state < EncounterState.ToBeDecided) + _instance.SetBossState((uint)bossId, state); + } + + return Result.Ok; + } + + Result ParseAdditionalData() + { + if (!_doc.RootElement.TryGetProperty("AdditionalData", out JsonElement moreData)) + return Result.Ok; + + if (moreData.ValueKind != JsonValueKind.Object) + { + Log.outError(LogFilter.Scripts, $"Additional data is not an object for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.AdditionalDataIsNotAnObject; + } + + foreach (PersistentInstanceScriptValueBase valueBase in _instance.GetPersistentScriptValues()) + { + if (moreData.TryGetProperty(valueBase.GetName(), out JsonElement value) && value.ValueKind != JsonValueKind.Null) + { + if (value.ValueKind != JsonValueKind.Number) + { + Log.outError(LogFilter.Scripts, $"Additional data value for key {valueBase.GetName()} is not a number for instance {GetInstanceId()} [{GetMapId()}-{GetMapName()} | {GetDifficultyId()}-{GetDifficultyName()}]"); + return Result.AdditionalDataUnexpectedValueType; + } + + if (value.TryGetDouble(out double doubleValue)) + valueBase.LoadValue(doubleValue); + else + valueBase.LoadValue(value.GetInt64()); + } + } + + return Result.Ok; + } + + uint GetInstanceId() { return _instance.instance.GetInstanceId(); } + + uint GetMapId() { return _instance.instance.GetId(); } + + string GetMapName() { return _instance.instance.GetMapName(); } + + uint GetDifficultyId() { return (uint)_instance.instance.GetDifficultyID(); } + + string GetDifficultyName() { return CliDB.DifficultyStorage.LookupByKey(_instance.instance.GetDifficultyID()).Name; } + } + + class InstanceScriptDataWriter + { + InstanceScript _instance; + JsonObject _doc = new(); + + public InstanceScriptDataWriter(InstanceScript instance) + { + _instance = instance; + } + + public string GetString() + { + using var stream = new MemoryStream(); + using (var writer = new Utf8JsonWriter(stream)) + { + _doc.WriteTo(writer); + } + + return Encoding.UTF8.GetString(stream.ToArray()); + } + + public void FillData(bool withValues = true) + { + _doc.Add("Header", _instance.GetHeader()); + + JsonArray bossStates = new(); + for (uint bossId = 0; bossId < _instance.GetEncounterCount(); ++bossId) + bossStates.Add(JsonValue.Create((int)(withValues ? _instance.GetBossState(bossId) : EncounterState.NotStarted))); + + _doc.Add("BossStates", bossStates); + + if (!_instance.GetPersistentScriptValues().Empty()) + { + JsonObject moreData = new(); + foreach (PersistentInstanceScriptValueBase additionalValue in _instance.GetPersistentScriptValues()) + { + if (withValues) + { + UpdateAdditionalSaveDataEvent data = additionalValue.CreateEvent(); + if (data.Value is double) + moreData.Add(data.Key, (double)data.Value); + else + moreData.Add(data.Key, (long)data.Value); + } + else + moreData.Add(additionalValue.GetName(), null); + } + + _doc.Add("AdditionalData", moreData); + } + } + + public void FillDataFrom(string data) + { + try + { + _doc = JsonNode.Parse(data).AsObject(); + } + catch (JsonException ex) + { + FillData(false); + } + } + + public void SetBossState(UpdateBossStateSaveDataEvent data) + { + var array = _doc["BossStates"].AsArray(); + array[(int)data.BossId] = (int)data.NewState; + } + + public void SetAdditionalData(UpdateAdditionalSaveDataEvent data) + { + var jObject = _doc["AdditionalData"].AsObject(); + if (data.Value is double) + jObject[data.Key] = (double)data.Value; + else + jObject[data.Key] = (long)data.Value; + } + } +} diff --git a/Source/Game/Maps/Map.cs b/Source/Game/Maps/Map.cs index ecccd360a..b8819e07c 100644 --- a/Source/Game/Maps/Map.cs +++ b/Source/Game/Maps/Map.cs @@ -4990,20 +4990,18 @@ namespace Game.Maps return Global.ObjectMgr.GetScriptName(i_script_id); } - public void UpdateInstanceLock(DungeonEncounterRecord dungeonEncounter, UpdateSaveDataEvent updateSaveDataEvent) + public void UpdateInstanceLock(UpdateBossStateSaveDataEvent updateSaveDataEvent) { if (i_instanceLock != null) { - uint instanceCompletedEncounters = i_instanceLock.GetData().CompletedEncountersMask; - if (dungeonEncounter != null) - instanceCompletedEncounters |= 1u << dungeonEncounter.Bit; + uint instanceCompletedEncounters = i_instanceLock.GetData().CompletedEncountersMask | (1u << updateSaveDataEvent.DungeonEncounter.Bit); MapDb2Entries entries = new(GetEntry(), GetMapDifficulty()); SQLTransaction trans = new(); if (entries.IsInstanceIdBound()) - Global.InstanceLockMgr.UpdateSharedInstanceLock(trans, new InstanceLockUpdateEvent(GetInstanceId(), i_data.GetSaveData(), instanceCompletedEncounters, dungeonEncounter)); + Global.InstanceLockMgr.UpdateSharedInstanceLock(trans, new InstanceLockUpdateEvent(GetInstanceId(), i_data.GetSaveData(), instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter)); foreach (var player in GetPlayers()) { @@ -5018,7 +5016,49 @@ namespace Game.Maps bool isNewLock = playerLock == null || playerLock.GetData().CompletedEncountersMask == 0 || playerLock.IsExpired(); - InstanceLock newLock = Global.InstanceLockMgr.UpdateInstanceLockForPlayer(trans, player.GetGUID(), entries, new InstanceLockUpdateEvent(GetInstanceId(), i_data.UpdateSaveData(oldData, updateSaveDataEvent), instanceCompletedEncounters, dungeonEncounter)); + InstanceLock newLock = Global.InstanceLockMgr.UpdateInstanceLockForPlayer(trans, player.GetGUID(), entries, new InstanceLockUpdateEvent(GetInstanceId(), i_data.UpdateBossStateSaveData(oldData, updateSaveDataEvent), instanceCompletedEncounters, updateSaveDataEvent.DungeonEncounter)); + + if (isNewLock) + { + InstanceSaveCreated data = new(); + data.Gm = player.IsGameMaster(); + player.SendPacket(data); + + player.GetSession().SendCalendarRaidLockoutAdded(newLock); + } + } + + DB.Characters.CommitTransaction(trans); + } + } + + public void UpdateInstanceLock(UpdateAdditionalSaveDataEvent updateSaveDataEvent) + { + if (i_instanceLock != null) + { + uint instanceCompletedEncounters = i_instanceLock.GetData().CompletedEncountersMask; + + MapDb2Entries entries = new(GetEntry(), GetMapDifficulty()); + + SQLTransaction trans = new(); + + if (entries.IsInstanceIdBound()) + Global.InstanceLockMgr.UpdateSharedInstanceLock(trans, new InstanceLockUpdateEvent(GetInstanceId(), i_data.GetSaveData(), instanceCompletedEncounters, null)); + + foreach (var player in GetPlayers()) + { + // never instance bind GMs with GM mode enabled + if (player.IsGameMaster()) + continue; + + InstanceLock playerLock = Global.InstanceLockMgr.FindActiveInstanceLock(player.GetGUID(), entries); + string oldData = ""; + if (playerLock != null) + oldData = playerLock.GetData().Data; + + bool isNewLock = playerLock == null || playerLock.GetData().CompletedEncountersMask == 0 || playerLock.IsExpired(); + + InstanceLock newLock = Global.InstanceLockMgr.UpdateInstanceLockForPlayer(trans, player.GetGUID(), entries, new InstanceLockUpdateEvent(GetInstanceId(), i_data.UpdateAdditionalSaveData(oldData, updateSaveDataEvent), instanceCompletedEncounters, null)); if (isNewLock) { diff --git a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/InstanceBlackrockDepths.cs b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/InstanceBlackrockDepths.cs index b0dabb00f..158fbfb7e 100644 --- a/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/InstanceBlackrockDepths.cs +++ b/Source/Scripts/EasternKingdoms/BlackrockMountain/BlackrockDepths/InstanceBlackrockDepths.cs @@ -114,9 +114,6 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths class instance_blackrock_depths_InstanceMapScript : InstanceScript { - uint[] encounter = new uint[MiscConst.MaxEncounter]; - string str_data; - ObjectGuid EmperorGUID; ObjectGuid PhalanxGUID; ObjectGuid MagmusGUID; @@ -155,6 +152,7 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths public instance_blackrock_depths_InstanceMapScript(InstanceMap map) : base(map) { SetHeaders("BRD"); + SetBossNumber(MiscConst.MaxEncounter); BarAleCount = 0; GhostKillCount = 0; @@ -238,40 +236,30 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths switch (type) { case DataTypes.TypeRingOfLaw: - encounter[0] = data; + SetBossState(0, (EncounterState)data); break; case DataTypes.TypeVault: - encounter[1] = data; + SetBossState(1, (EncounterState)data); break; case DataTypes.TypeBar: if (data == (uint)EncounterState.Special) ++BarAleCount; else - encounter[2] = data; + SetBossState(2, (EncounterState)data); break; case DataTypes.TypeTombOfSeven: - encounter[3] = data; + SetBossState(3, (EncounterState)data); break; case DataTypes.TypeLyceum: - encounter[4] = data; + SetBossState(4, (EncounterState)data); break; case DataTypes.TypeIronHall: - encounter[5] = data; + SetBossState(5, (EncounterState)data); break; case DataTypes.DataGhostkill: GhostKillCount += data; break; } - - if (data == (uint)EncounterState.Done || GhostKillCount >= MiscConst.TombOfSevenBossNum) - { - OutSaveInstData(); - - str_data = $"{encounter[0]} {encounter[1]} {encounter[2]} {encounter[3]} {encounter[4]} {encounter[5]} {GhostKillCount}"; - - SaveToDB(); - OutSaveInstDataComplete(); - } } public override uint GetData(uint type) @@ -279,20 +267,20 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths switch (type) { case DataTypes.TypeRingOfLaw: - return encounter[0]; + return (uint)GetBossState(0); case DataTypes.TypeVault: - return encounter[1]; + return (uint)GetBossState(1); case DataTypes.TypeBar: - if (encounter[2] == (uint)EncounterState.InProgress && BarAleCount == 3) + if (GetBossState(2) == EncounterState.InProgress && BarAleCount == 3) return (uint)EncounterState.Special; else - return encounter[2]; + return (uint)GetBossState(2); case DataTypes.TypeTombOfSeven: - return encounter[3]; + return (uint)GetBossState(3); case DataTypes.TypeLyceum: - return encounter[4]; + return (uint)GetBossState(4); case DataTypes.TypeIronHall: - return encounter[5]; + return (uint)GetBossState(5); case DataTypes.DataGhostkill: return GhostKillCount; } @@ -343,41 +331,6 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.BlackrockDepths return ObjectGuid.Empty; } - public override string GetSaveData() - { - return str_data; - } - - public override void Load(string str) - { - if (str.IsEmpty()) - { - - OutLoadInstDataFail(); - return; - } - - OutLoadInstData(str); - - StringArguments loadStream = new(str); - - for (var i = 0; i < encounter.Length; ++i) - encounter[i] = loadStream.NextUInt32(); - - GhostKillCount = loadStream.NextUInt32(); - - for (byte i = 0; i < encounter.Length; ++i) - if (encounter[i] == (uint)EncounterState.InProgress) - encounter[i] = (uint)EncounterState.NotStarted; - - if (GhostKillCount > 0 && GhostKillCount < MiscConst.TombOfSevenBossNum) - GhostKillCount = 0;//reset tomb of seven event - if (GhostKillCount >= MiscConst.TombOfSevenBossNum) - GhostKillCount = MiscConst.TombOfSevenBossNum; - - OutLoadInstDataComplete(); - } - void TombOfSevenEvent() { if (GhostKillCount < MiscConst.TombOfSevenBossNum && !TombBossGUIDs[TombEventCounter].IsEmpty()) diff --git a/Source/Scripts/EasternKingdoms/BlackrockMountain/MoltenCore/InstanceMoltenCore.cs b/Source/Scripts/EasternKingdoms/BlackrockMountain/MoltenCore/InstanceMoltenCore.cs index 9b34d5633..b9eea04e1 100644 --- a/Source/Scripts/EasternKingdoms/BlackrockMountain/MoltenCore/InstanceMoltenCore.cs +++ b/Source/Scripts/EasternKingdoms/BlackrockMountain/MoltenCore/InstanceMoltenCore.cs @@ -230,7 +230,7 @@ namespace Scripts.EasternKingdoms.BlackrockMountain.MoltenCore return true; } - void ReadSaveDataMore(string data) + public override void AfterDataLoad() { if (CheckMajordomoExecutus()) _executusSchedule = true;