refactor(load): switch to InventoryService for entitlements

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-05-31 16:12:27 -04:00
parent 91909c5755
commit 1113e52f94

View File

@@ -10,6 +10,7 @@ using PreReleaseInfoDto = SVSim.EmulatedEntrypoint.Models.Dtos.PreReleaseInfo;
using SVSim.Database.Repositories.Globals;
using SVSim.Database.Repositories.Viewer;
using SVSim.Database.Services;
using SVSim.Database.Services.Inventory;
using SVSim.EmulatedEntrypoint.Constants;
using SVSim.EmulatedEntrypoint.Infrastructure;
using SVSim.EmulatedEntrypoint.Models.Dtos;
@@ -42,26 +43,24 @@ public class LoadController : SVSimController
private readonly IViewerRepository _viewerRepository;
private readonly IGlobalsRepository _globalsRepository;
private readonly ICardAcquisitionService _acquisition;
private readonly IGameConfigService _config;
private readonly IBattlePassService _battlePass;
private readonly IViewerMissionStateService _missionState;
private readonly SVSimDbContext _db;
private readonly IViewerEntitlements _entitlements;
private readonly IInventoryService _inv;
public LoadController(IViewerRepository viewerRepository, IGlobalsRepository globalsRepository,
ICardAcquisitionService acquisition, IGameConfigService config,
IGameConfigService config,
IBattlePassService battlePass, IViewerMissionStateService missionState,
SVSimDbContext db, IViewerEntitlements entitlements)
SVSimDbContext db, IInventoryService inv)
{
_viewerRepository = viewerRepository;
_globalsRepository = globalsRepository;
_acquisition = acquisition;
_config = config;
_battlePass = battlePass;
_missionState = missionState;
_db = db;
_entitlements = entitlements;
_inv = inv;
}
[HttpPost("index")]
@@ -84,7 +83,9 @@ public class LoadController : SVSimController
// .AsNoTracking() — the local `viewer` instance is detached, and the service's writes
// (on a separate tracked instance) won't appear on this snapshot. Without the re-fetch,
// the response payload would be one /load/index behind on newly-granted cosmetics.
await _acquisition.BackfillCosmeticsAsync(viewer.Id);
await using var tx = await _inv.BeginAsync(viewer.Id, ct);
await tx.BackfillCardCosmeticsAsync(ct);
await tx.CommitAsync(ct);
// Lazy-materialize mission/achievement state. Idempotent — safe to call every /load/index.
await _missionState.EnsureCurrentAsync(viewer.Id);
@@ -125,9 +126,9 @@ public class LoadController : SVSimController
// re-confirm the filter if we later move to Option B and start iterating card-sets.
// Owned-card projection (incl. the freeplay "all cards" path) lives in the entitlements
// service so both modes share one definition.
var allCardsAsOwned = await _entitlements.EffectiveOwnedCardsAsync(viewer, ct);
var allCardsAsOwned = await _inv.EffectiveOwnedCardsAsync(viewer, ct);
var cosmetics = await _entitlements.EffectiveCosmeticsAsync(viewer, ct);
var cosmetics = await _inv.EffectiveCosmeticsAsync(viewer, ct);
var classExpCurve = await _globalsRepository.GetClassExpCurve();
List<ClassExp> classExps = new();
@@ -168,10 +169,10 @@ public class LoadController : SVSimController
UserInfo = new UserInfo(deviceType, viewer),
UserCurrency = new UserCurrency(viewer)
{
Crystals = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Crystal),
TotalCrystals = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Crystal),
Rupees = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Rupee),
RedEther = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.RedEther),
Crystals = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Crystal),
TotalCrystals = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Crystal),
Rupees = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Rupee),
RedEther = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.RedEther),
},
UserItems = viewer.Items.Select(item => new UserItem(item)).ToList(),
SpotPoint = checked((int)viewer.Currency.SpotPoints),