From 40dad82559dcda96fb5d8162a5971e89c6c6aa23 Mon Sep 17 00:00:00 2001 From: neckfire Date: Tue, 14 Jul 2026 13:46:17 +0200 Subject: [PATCH] feat(store): populate Aurum/cosmetic shops from Vanities GetStoreItems now also serves the cosmetic stores the client queries (AurumShop, and the DailyShop_/WeeklyShop_ rotations) from the Vanities title data: every vanity with StoreData.Amount > 0 is offered for that price in Aurum (AU). AurumShop lists the full priced catalogue (632 items); the daily/weekly ids show a deterministic rotating slice so they stay stable within a period but change across periods. Co-Authored-By: Claude Opus 4.8 --- .../Controllers/ClientController.cs | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/src/Prospect.Server.Api/Controllers/ClientController.cs b/src/Prospect.Server.Api/Controllers/ClientController.cs index a5aee37..d1fad77 100644 --- a/src/Prospect.Server.Api/Controllers/ClientController.cs +++ b/src/Prospect.Server.Api/Controllers/ClientController.cs @@ -210,6 +210,53 @@ public class ClientController : Controller _logger.LogWarning(e, "Failed to build store items for store {StoreId}", storeId); } + // Cosmetic / premium stores are backed by the Vanities title data (not Blueprints): + // each vanity carries its price in StoreData.Amount, paid in Aurum. AurumShop lists + // the whole priced catalogue; the daily/weekly rotations (ids from RequestStore + // RotationData) show a deterministic slice so they change over time but stay stable + // within a period. + var isAurumShop = storeId == "AurumShop"; + var isDailyShop = storeId.StartsWith("DailyShop_"); + var isWeeklyShop = storeId.StartsWith("WeeklyShop_"); + if (store.Count == 0 && (isAurumShop || isDailyShop || isWeeklyShop)) + { + try + { + var vanityData = _titleDataService.Find(new List { "Vanities" }); + var vanities = JsonSerializer.Deserialize>(vanityData["Vanities"]); + var priced = vanities? + .Where(v => v.StoreData != null && v.StoreData.Amount > 0) + .OrderBy(v => v.Name, StringComparer.Ordinal) + .ToList() ?? new List(); + + IEnumerable selection = priced; + if ((isDailyShop || isWeeklyShop) && priced.Count > 0) + { + var size = isWeeklyShop ? 12 : 6; + int.TryParse(storeId[(storeId.IndexOf('_') + 1)..], out var rotation); + var start = (int)(((long)rotation * size) % priced.Count); + selection = Enumerable.Range(0, Math.Min(size, priced.Count)) + .Select(i => priced[(start + i) % priced.Count]); + } + + uint position = 0; + foreach (var vanity in selection) + { + store.Add(new FStoreItem + { + ItemId = vanity.Name, + VirtualCurrencyPrices = new Dictionary { ["AU"] = (uint)vanity.StoreData.Amount }, + RealCurrencyPrices = new Dictionary(), + DisplayPosition = position++, + }); + } + } + catch (Exception e) + { + _logger.LogWarning(e, "Failed to build vanity store {StoreId}", storeId); + } + } + _logger.LogInformation("GetStoreItems '{StoreId}': {Count} item(s)", storeId, store.Count); return Ok(new ClientResponse {