From 4e0b6440d928899ff1e30830d697c7726c15c155 Mon Sep 17 00:00:00 2001 From: Yury Date: Tue, 25 Mar 2025 18:51:29 +0200 Subject: [PATCH] Fix job boards --- .../Models/Data/DatabaseModels.cs | 10 ++ .../Functions/ClaimActiveContract.cs | 43 +++++- .../RequestActiveObjectivesAndBoardsData.cs | 141 +++++++++--------- 3 files changed, 116 insertions(+), 78 deletions(-) diff --git a/src/Prospect.Server.Api/Models/Data/DatabaseModels.cs b/src/Prospect.Server.Api/Models/Data/DatabaseModels.cs index baadfb3..930d0c5 100644 --- a/src/Prospect.Server.Api/Models/Data/DatabaseModels.cs +++ b/src/Prospect.Server.Api/Models/Data/DatabaseModels.cs @@ -1,4 +1,5 @@ using System.Text.Json.Serialization; +using Prospect.Server.Api.Services.CloudScript.Models.Data; namespace Prospect.Server.Api.Models.Data; @@ -12,4 +13,13 @@ public class PlayerBalance [JsonPropertyName("IN")] public int InsuranceTokens { get; set; } +} + +public class JobBoardsData +{ + [JsonPropertyName("lastBoardRefreshTimeUtc")] + public FYTimestamp LastBoardRefreshTimeUtc { get; set; } + + [JsonPropertyName("boards")] + public List Boards { get; set; } } \ No newline at end of file diff --git a/src/Prospect.Server.Api/Services/CloudScript/Functions/ClaimActiveContract.cs b/src/Prospect.Server.Api/Services/CloudScript/Functions/ClaimActiveContract.cs index 4a127ca..e787e28 100644 --- a/src/Prospect.Server.Api/Services/CloudScript/Functions/ClaimActiveContract.cs +++ b/src/Prospect.Server.Api/Services/CloudScript/Functions/ClaimActiveContract.cs @@ -50,6 +50,8 @@ public class ClaimActiveContract : ICloudScriptFunction{"Contracts", "Blueprints"}); + var titleData = _titleDataService.Find(new List{ "Contracts", "Blueprints", "Jobs", "LevelData" }); var contracts = JsonSerializer.Deserialize>(titleData["Contracts"]); - var contract = contracts[request.ContractID]; - if (contract == null) { + if (!contracts.TryGetValue(request.ContractID, out var contract)) { return new FYClaimCompletedActiveContractRewardsResult { UserID = userId, @@ -82,16 +83,17 @@ public class ClaimActiveContract : ICloudScriptFunction{"ContractsActive", "ContractsOneTimeCompleted", "Balance", "Inventory", factionKey} + new List{"ContractsActive", "ContractsOneTimeCompleted", "Balance", "Inventory", factionKey, "JobBoardsData" } ); var factionProgression = JsonSerializer.Deserialize(userData[factionKey].Value); var contractsActive = JsonSerializer.Deserialize(userData["ContractsActive"].Value); var contractsCompleted = JsonSerializer.Deserialize(userData["ContractsOneTimeCompleted"].Value); + var jobBoardsData = JsonSerializer.Deserialize(userData["JobBoardsData"].Value); var balance = JsonSerializer.Deserialize(userData["Balance"].Value); var inventory = JsonSerializer.Deserialize>(userData["Inventory"].Value); - var targetContractIdx = contractsActive.Contracts.FindIndex(item => item.ContractID == request.ContractID); + var targetContractIdx = contractsActive.Contracts.FindIndex(item => item.ContractID == contract.Name); if (targetContractIdx == -1) { return new FYClaimCompletedActiveContractRewardsResult { @@ -106,6 +108,7 @@ public class ClaimActiveContract : ICloudScriptFunction itemsUpdatedOrRemoved = []; HashSet deletedItemsIds = []; + // TODO: Optimize for (var i = 0; i < contract.Objectives.Length; i++) { var objective = contract.Objectives[i]; int remaining = objective.MaxProgress; @@ -211,10 +214,33 @@ public class ClaimActiveContract : ICloudScriptFunction>(titleData["LevelData"]); + var levels = levelsData[contract.Faction]; + var jobs = JsonSerializer.Deserialize>>(titleData["Jobs"]); + var level = levels.Length - Array.FindIndex(levels, (int xp) => { + return factionProgression >= xp; + }); + + var factionBoard = jobBoardsData.Boards.Find(c => c.FactionId == contract.Faction); + var idx = Array.FindIndex(difficulties, d => d == difficulty); + var factionJobs = jobs[contract.Faction]; + var jobsAvailable = Array.FindAll(factionJobs[difficulty], (string jobId) => { + return level >= contracts[jobId].UnlockData.Level; + }); + // If player completes a job, it means he has at least one unlocked anyway. + newContractIdOnBoard = jobsAvailable[rnd.Next(jobsAvailable.Length)]; + factionBoard.Contracts[idx].ContractId = newContractIdOnBoard; } + // TODO: Check for next unlock in contracts instead of relying on client var newContracts = new List(); foreach (var contractIdToUnlock in request.ContractsToUnlock) { var contractToUnlock = contracts[contractIdToUnlock]; @@ -235,6 +261,7 @@ public class ClaimActiveContract : ICloudScriptFunction ExecuteAsync(FYQueryFactionProgressionRequest request) @@ -26,10 +34,65 @@ public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction{"ContractsActive"}); - var contractsActive = JsonSerializer.Deserialize(userData["ContractsActive"].Value); - // TODO: Get player's contract boards and refresh + var userData = await _userDataService.FindAsync(userId, userId, new List{ "ContractsActive", "JobBoardsData", "FactionProgressionKorolev", "FactionProgressionICA", "FactionProgressionOsiris" }); + var contractsActive = JsonSerializer.Deserialize(userData["ContractsActive"].Value); + var jobBoardsData = JsonSerializer.Deserialize(userData["JobBoardsData"].Value); + + var now = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds(); + var lastBoardRefreshTimeUtc = jobBoardsData.LastBoardRefreshTimeUtc; + var boards = jobBoardsData.Boards; + // The boards are updated once in 3 hours + if (now >= lastBoardRefreshTimeUtc.Seconds + 60 * 60 * 3) { + var titleData = _titleDataService.Find(new List { "Contracts", "Jobs", "LevelData" }); + + var contracts = JsonSerializer.Deserialize>(titleData["Contracts"]); + var jobs = JsonSerializer.Deserialize>>(titleData["Jobs"]); + var levelsData = JsonSerializer.Deserialize>(titleData["LevelData"]); + var currentQuests = new Dictionary> { + ["Korolev"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, + ["Osiris"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, + ["ICA"] = new Dictionary { ["Easy"] = false, ["Medium"] = false, ["Hard"] = false }, + }; + + foreach (var contract in contractsActive.Contracts) { + var parts = contract.ContractID.Split('-'); + if (parts[0] != "NEW") { + continue; + } + var difficulty = parts[1]; + var faction = parts[2] == "KOR" ? "Korolev" : parts[2]; + currentQuests[faction][difficulty] = true; + } + + for (var i = 0; i < factions.Length; i++) { + var faction = factions[i]; + var factionProgression = JsonSerializer.Deserialize(userData[$"FactionProgression{faction}"].Value); + var levels = levelsData[faction]; + var level = levels.Length - Array.FindIndex(levels, (int xp) => { + return factionProgression >= xp; + }); + + for (var j = 0; j < difficulties.Length; j++) { + var difficulty = difficulties[j]; + if (currentQuests[faction][difficulty]) { + continue; + } + var factionJobs = jobs[faction]; + var jobsAvailable = Array.FindAll(factionJobs[difficulty], (string jobId) => { + return level >= contracts[jobId].UnlockData.Level; + }); + string jobId = jobsAvailable.Length > 0 ? jobsAvailable[rnd.Next(jobsAvailable.Length)] : factionJobs[difficulty][0]; + boards[i].Contracts[j] = new FYFactionContractData { ContractId = jobId }; + } + } + lastBoardRefreshTimeUtc.Seconds = now; + + await _userDataService.UpdateAsync( + userId, userId, + new Dictionary { ["JobBoardsData"] = JsonSerializer.Serialize(jobBoardsData) } + ); + } return new FYGetPlayerContractsResult { @@ -38,72 +101,10 @@ public class RequestActiveObjectivesAndBoardsData : ICloudScriptFunction - { - new FYFactionContractsData - { - FactionId = "ICA", - Contracts = new List - { - new FYFactionContractData - { - ContractId = "NEW-Easy-ICA-Gather-1", - }, - new FYFactionContractData - { - ContractId = "NEW-Medium-ICA-Uplink-1", - }, - new FYFactionContractData - { - ContractId = "NEW-Hard-ICA-Uplink-1", - } - } - }, - new FYFactionContractsData - { - FactionId = "Korolev", - Contracts = new List - { - new FYFactionContractData - { - ContractId = "NEW-Easy-KOR-Mine-4", - }, - new FYFactionContractData - { - ContractId = "NEW-Medium-KOR-Mine-1", - }, - new FYFactionContractData - { - ContractId = "NEW-Hard-KOR-PvP-6", - } - } - }, - new FYFactionContractsData - { - FactionId = "Osiris", - Contracts = new List - { - new FYFactionContractData - { - ContractId = "NEW-Easy-Osiris-Brightcaps-1", - }, - new FYFactionContractData - { - ContractId = "NEW-Medium-Osiris-Gather-1", - }, - new FYFactionContractData - { - ContractId = "NEW-Hard-Osiris-Gather-7", - } - } - } - }, - LastBoardRefreshTimeUtc = new FYTimestamp - { - Seconds = (int)DateTimeOffset.UtcNow.ToUnixTimeSeconds() - } + Boards = boards, + LastBoardRefreshTimeUtc = lastBoardRefreshTimeUtc }, - RefreshHours24UtcFromBackend = 12 + RefreshHours24UtcFromBackend = 12 // Doesn't seem to work }; } } \ No newline at end of file