using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using WingsEmu.Core.Extensions; using WingsEmu.Core.Generics; using WingsEmu.DTOs.Quests; using WingsEmu.Packets.Enums; namespace WingsEmu.Game.Quests; public class BasicQuestContainer : IQuestContainer { private readonly ConcurrentDictionary _activeQuests = new(); private readonly ConcurrentDictionary _completedPeriodicQuests = new(); private readonly ConcurrentDictionary _completedQuests = new(); private readonly ConcurrentDictionary<(int, int), CompletedScriptsDto> _completedScripts = new(); private readonly ConcurrentDictionary> _completedScriptsByType = new(); private readonly ConcurrentDictionary> _questsByQuestType = new(); private int _soundFlowersPendingToStart; public bool HasCompletedScriptByIndex(int scriptId, int scriptIndex) => _completedScripts.ContainsKey((scriptId, scriptIndex)); public bool HasCompletedQuest(int questId) => _completedQuests.ContainsKey(questId); public IEnumerable GetCurrentQuests() => _activeQuests.Values; public IEnumerable GetCompletedQuests() => _completedQuests.Values; public IEnumerable GetCompletedPeriodicQuests() => _completedPeriodicQuests.Values.Cast().ToArray(); public IEnumerable GetCurrentQuestsByType(QuestType questType) { return _activeQuests.Values.Where(s => s.Quest.QuestType == questType).ToArray(); } public IEnumerable GetCurrentQuestsByTypes(IReadOnlyCollection questTypes) { return _activeQuests.Values.Where(s => questTypes.Contains(s.Quest.QuestType)).ToArray(); } public IEnumerable GetQuestsProgress() => _activeQuests.Values.Cast().ToList(); public CharacterQuest GetCurrentQuest(int questId) => _activeQuests.GetOrDefault(questId); public bool HasQuestWithQuestType(QuestType questType) => _questsByQuestType.ContainsKey(questType); public bool HasQuestWithId(int questId) => _activeQuests.ContainsKey(questId); public void AddActiveQuest(CharacterQuest quest) { if (_activeQuests.ContainsKey(quest.QuestId)) { return; } _activeQuests.TryAdd(quest.QuestId, quest); if (!_questsByQuestType.TryGetValue(quest.Quest.QuestType, out ThreadSafeList characterQuests)) { characterQuests = new ThreadSafeList(); _questsByQuestType[quest.Quest.QuestType] = characterQuests; } characterQuests.Add(quest); } public void RemoveActiveQuest(int questId) { if (!_activeQuests.Remove(questId, out CharacterQuest quest)) { return; } if (!_questsByQuestType.TryGetValue(quest.Quest.QuestType, out ThreadSafeList characterQuests)) { return; } characterQuests.Remove(quest); } public void AddCompletedQuest(CharacterQuest quest) { if (_completedQuests.ContainsKey(quest.QuestId)) { return; } _completedQuests.TryAdd(quest.QuestId, quest); } public void RemoveCompletedQuest(int questId) => _completedQuests.TryRemove(questId, out _); public void RemoveCompletedScript(int scriptId, int scriptIndex) => _completedScripts.TryRemove((scriptId, scriptIndex), out _); public void RemoveAllCompletedScripts() => _completedScripts.Clear(); public void AddCompletedPeriodicQuest(CharacterQuest quest) { if (_completedPeriodicQuests.ContainsKey(quest.QuestId)) { return; } _completedPeriodicQuests.TryAdd(quest.QuestId, quest); } public void ClearCompletedPeriodicQuests() => _completedPeriodicQuests.Clear(); public IEnumerable GetCompletedScripts() => _completedScripts.Values.ToArray(); public IEnumerable GetCompletedScriptsByType(TutorialActionType scriptType) { if (!_completedScriptsByType.TryGetValue(scriptType, out ThreadSafeList list)) { return Array.Empty(); } return list; } public void SaveScript(int scriptId, int scriptIndex, TutorialActionType scriptType, DateTime savingDate) { var completedScript = new CompletedScriptsDto { ScriptId = scriptId, ScriptIndex = scriptIndex, CompletedDate = savingDate }; _completedScripts.TryAdd((scriptId, scriptIndex), completedScript); if (!_completedScriptsByType.TryGetValue(scriptType, out ThreadSafeList list)) { list = new ThreadSafeList(); _completedScriptsByType[scriptType] = list; } list.Add(completedScript); } public CompletedScriptsDto GetLastCompletedScript() { if (!_completedScripts.Any()) { return null; } return _completedScripts.OrderByDescending(s => s.Key.Item1).ThenByDescending(s => s.Key.Item2).FirstOrDefault().Value; } public CompletedScriptsDto GetLastCompletedScriptByType(TutorialActionType scriptType) { if (!_completedScriptsByType.ContainsKey(scriptType) || !_completedScriptsByType[scriptType].Any()) { return null; } return _completedScriptsByType[scriptType].OrderByDescending(s => s.ScriptId).ThenByDescending(s => s.ScriptIndex).FirstOrDefault(); } public void IncreasePendingSoundFlowerQuests() => _soundFlowersPendingToStart++; public void DecreasePendingSoundFlowerQuests() => _soundFlowersPendingToStart--; public int GetPendingSoundFlowerQuests() => _soundFlowersPendingToStart; }