Files
2026-10-14 06:59:51 +02:00

77 lines
3.7 KiB
C#

using Newtonsoft.Json.Linq;
using Campus_live_rewrite.api.dbs;
namespace Campus_live_rewrite.api.server
{
/// <summary>
/// The developer locker's extra avatar items: every avatar item any storefront sells (the
/// Watch store as generated AND its raw file - the generator hides some captured rows - every
/// other store file, admin-added rows) that avatar_items.json does
/// NOT list - 136 on 2026-09-26, mostly captured Watch rows ("Masquerade Peacock Gown", "UFO
/// Hat"...). /api/avatar/v4/items gives a developer the whole catalog; these are appended so a
/// developer owns every single item in the game. Shaped like avatar_items.json entries and
/// rebuilt at most every 10 minutes.
/// </summary>
public static class DevLocker
{
private static List<JObject>? _extra;
private static DateTime _builtAt;
private static readonly object _lock = new();
public static List<JObject> StoreOnlyAvatarItems(JArray catalog)
{
lock (_lock)
{
if (_extra != null && DateTime.UtcNow - _builtAt < TimeSpan.FromMinutes(10))
return _extra.Select(e => (JObject)e.DeepClone()).ToList();
var known = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
foreach (var e in catalog)
{
string k = PlayerDB.NormalizeAvatarItemDesc((string?)e["AvatarItemDesc"]);
if (k.Length > 0) known.Add(k);
}
var rows = new List<JToken>();
try { rows.AddRange(StoreGenerator.MergedWatchStore()["StoreItems"] as JArray ?? new JArray()); } catch { }
try
{
if (Directory.Exists(StoreCatalog.StoreDirectory))
foreach (var f in Directory.GetFiles(StoreCatalog.StoreDirectory, "*.json"))
{
try { rows.AddRange(JObject.Parse(File.ReadAllText(f))["StoreItems"] as JArray ?? new JArray()); } catch { }
}
} catch { }
foreach (int store in Enum.GetValues(typeof(Classes.StorefrontType)).Cast<int>().Distinct())
rows.AddRange(StoreEdits.Rows(store));
var extra = new List<JObject>();
foreach (var r in rows)
{
if (r["GiftDrop"] is not JObject gd) continue;
string desc = (string?)gd["AvatarItemDesc"] ?? "";
string key = PlayerDB.NormalizeAvatarItemDesc(desc);
if (key.Length == 0 || !known.Add(key)) continue;
extra.Add(new JObject
{
["AvatarItemDesc"] = desc,
["AvatarItemType"] = (int?)gd["AvatarItemType"] ?? 0,
["PlatformMask"] = -1,
["FriendlyName"] = (string?)gd["FriendlyName"] ?? "",
["Tooltip"] = (string?)gd["Tooltip"] ?? "",
["Rarity"] = (int?)gd["Rarity"] ?? 0,
["TagList"] = gd["TagList"]?.DeepClone(),
["AvatarItemId"] = (int?)gd["AvatarItemId"] ?? 0,
["IsBaseAvatarItem"] = false,
["CreatedAt"] = "2020-01-01T00:00:00Z",
["ThumbnailImage"] = (string?)gd["ThumbnailImageName"]
});
}
Console.WriteLine($"[items] dev locker: {extra.Count} store-only avatar item(s) added to the catalog's {catalog.Count}");
_extra = extra; _builtAt = DateTime.UtcNow;
return _extra.Select(e => (JObject)e.DeepClone()).ToList();
}
}
}
}