using SPTarkov.DI.Annotations; using SPTarkov.Server.Core.Models.Common; using SPTarkov.Server.Core.Models.Enums; using SPTarkov.Server.Core.Models.Spt.Config; using SPTarkov.Server.Core.Models.Spt.Mod; using SPTarkov.Server.Core.Servers; namespace SPTarkov.Server.Core.Services.Mod; [Injectable] public class CustomQuestService( DatabaseService databaseService, ConfigServer configServer, ServerLocalisationService serverLocalisationService ) { /// /// Create a new custom quest from a NewQuestDetails object. /// /// Quest details to be used for creation /// Result of the quest creation, remember to check it for errors! public CreateQuestResult CreateQuest(NewQuestDetails newQuestDetails) { var quest = newQuestDetails.NewQuest; var result = new CreateQuestResult(false, newQuestDetails.NewQuest.Id); var databaseQuests = databaseService.GetTables().Templates.Quests; if (!databaseQuests.TryAdd(quest.Id, quest)) { result.Errors.Add(serverLocalisationService.GetText("custom-quest-service_quest_id_already_exists", quest.Id)); return result; } var locales = newQuestDetails.Locales; if (locales.Count == 0) { result.Errors.Add(serverLocalisationService.GetText("custom-quest-service_no_languages_for_quest", quest.Id)); return result; } AddQuestLocales(locales, result); var side = newQuestDetails.LockedToSide; if (side.HasValue) { RestrictQuestSide(quest.Id, side.Value, result); } // No errors mean success result.Success = result.Errors.Count == 0; return result; } /// /// Adds quest locales to the database /// /// locales to add /// create quest result private void AddQuestLocales(Dictionary> locales, CreateQuestResult result) { var globalLocales = databaseService.GetLocales().Global; foreach (var (languageKey, entries) in locales) { if (entries.Count == 0) { result.Errors?.Add(serverLocalisationService.GetText("custom-quest-service_no_entries_for_language", languageKey)); continue; } if (!globalLocales.TryGetValue(languageKey, out var lazyLoadedLocales)) { result.Errors?.Add(serverLocalisationService.GetText("custom-quest-service_could_not_find_language_key", languageKey)); continue; } lazyLoadedLocales.AddTransformer(localeData => { if (localeData is null) { result.Errors?.Add(serverLocalisationService.GetText("custom-quest-service_locale_data_null", languageKey)); return null; } foreach (var (key, entry) in entries) { localeData.TryAdd(key, entry); } return localeData; }); } } /// /// Restricts a custom quest to a specific side. /// /// Quest id to restrict /// Side to restrict it to /// Result of the quest creation private void RestrictQuestSide(MongoId questId, PlayerSide side, CreateQuestResult result) { var questConfig = configServer.GetConfig(); // ReSharper disable once SwitchStatementHandlesSomeKnownEnumValuesWithDefault switch (side) { case PlayerSide.Usec: questConfig.UsecOnlyQuests.Add(questId); break; case PlayerSide.Bear: questConfig.BearOnlyQuests.Add(questId); break; case PlayerSide.Savage: result.Errors.Add(serverLocalisationService.GetText("custom-quest-service_invalid_side", result.QuestId)); break; } } }