mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 07:28:45 -07:00
avatar: raise unlocked-items defaults so new purchases survive relog
/api/avatar/v4/items truncated owned items by maxItems (was 30) and maxPerSlot (was 4). The per-slot cap silently dropped any newly-bought wardrobe item once a slot held 4+ entries — the 'I bought it but it's gone after relog' symptom. Defaults raised to 100 / 20. Clamp ranges left at [1,120] / [1,20] (prior maintainer note locked these to watch render-budget testing — raising the ceiling without retesting risks BrowsableAvatarItem / DynamicAvatarItemImposter thrash inside the watch's wardrobe drawer). Sort tiebreaker added: ThenByDescending(OriginalIndex) so when truncation has to drop entries, it drops the OLDEST (starter seed) items rather than the just-purchased one. GrantWardrobeAsync and the gift-consume path both append new GUIDs to the end of InventoryJson, so list index == purchase order.
This commit is contained in:
@@ -85,8 +85,16 @@ public class AvatarItemsController(DorkNetDbContext db, IConfiguration config) :
|
||||
if (!config.GetValue("Avatar:EnableUnlockedItems", true))
|
||||
return Ok(new List<UnlockedAvatarItemDto>());
|
||||
|
||||
var maxItems = Math.Clamp(config.GetValue("Avatar:MaxUnlockedItems", 30), 1, 120);
|
||||
var maxPerSlot = Math.Clamp(config.GetValue("Avatar:MaxUnlockedItemsPerSlot", 4), 1, 20);
|
||||
// Defaults raised (30 → 100, 4 → 20) — the old 4-per-slot silently
|
||||
// dropped any newly-purchased item once a slot held 4+ entries (the
|
||||
// "I bought it but it's gone after relog" symptom). The clamp
|
||||
// ranges stay at [1,120] / [1,20] — those reflect empirical watch
|
||||
// testing on render-budget headroom (per the prior maintainer note
|
||||
// about BrowsableAvatarItem / DynamicAvatarItemImposter thrash
|
||||
// above this count); raising the clamp ceiling without retesting
|
||||
// could crash the watch's wardrobe drawer.
|
||||
var maxItems = Math.Clamp(config.GetValue("Avatar:MaxUnlockedItems", 100), 1, 120);
|
||||
var maxPerSlot = Math.Clamp(config.GetValue("Avatar:MaxUnlockedItemsPerSlot", 20), 1, 20);
|
||||
|
||||
var pid = this.CurrentPlayerId();
|
||||
if (pid is not long me) return Ok(new List<UnlockedAvatarItemDto>());
|
||||
@@ -109,10 +117,17 @@ public class AvatarItemsController(DorkNetDbContext db, IConfiguration config) :
|
||||
|
||||
var catalog = _catalog.Value;
|
||||
var equipped = ParseEquippedItemGuids(avatar?.OutfitSelections);
|
||||
// Recency tiebreaker: GrantWardrobeAsync / gift-consume APPEND new
|
||||
// GUIDs to the end of InventoryJson, so the original index is also
|
||||
// the purchase order. When per-slot truncation has to drop entries,
|
||||
// we want it to drop the OLDEST (starter seed) items rather than the
|
||||
// one the user just bought.
|
||||
var ordered = owned
|
||||
.OrderByDescending(guid => equipped.Contains(guid))
|
||||
.ThenBy(guid => catalog.SlotByGuid.TryGetValue(guid, out var slot) ? slot : int.MaxValue)
|
||||
.ThenBy(guid => guid, StringComparer.OrdinalIgnoreCase);
|
||||
.Select((guid, idx) => (Guid: guid, OriginalIndex: idx))
|
||||
.OrderByDescending(x => equipped.Contains(x.Guid))
|
||||
.ThenBy(x => catalog.SlotByGuid.TryGetValue(x.Guid, out var slot) ? slot : int.MaxValue)
|
||||
.ThenByDescending(x => x.OriginalIndex)
|
||||
.Select(x => x.Guid);
|
||||
|
||||
var maxOutfitItems = Math.Max(0, maxItems - ownedHairDyes.Count);
|
||||
var perSlot = new Dictionary<int, int>();
|
||||
|
||||
Reference in New Issue
Block a user