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.Globals;
using SVSim.Database.Repositories.Viewer; using SVSim.Database.Repositories.Viewer;
using SVSim.Database.Services; using SVSim.Database.Services;
using SVSim.Database.Services.Inventory;
using SVSim.EmulatedEntrypoint.Constants; using SVSim.EmulatedEntrypoint.Constants;
using SVSim.EmulatedEntrypoint.Infrastructure; using SVSim.EmulatedEntrypoint.Infrastructure;
using SVSim.EmulatedEntrypoint.Models.Dtos; using SVSim.EmulatedEntrypoint.Models.Dtos;
@@ -42,26 +43,24 @@ public class LoadController : SVSimController
private readonly IViewerRepository _viewerRepository; private readonly IViewerRepository _viewerRepository;
private readonly IGlobalsRepository _globalsRepository; private readonly IGlobalsRepository _globalsRepository;
private readonly ICardAcquisitionService _acquisition;
private readonly IGameConfigService _config; private readonly IGameConfigService _config;
private readonly IBattlePassService _battlePass; private readonly IBattlePassService _battlePass;
private readonly IViewerMissionStateService _missionState; private readonly IViewerMissionStateService _missionState;
private readonly SVSimDbContext _db; private readonly SVSimDbContext _db;
private readonly IViewerEntitlements _entitlements; private readonly IInventoryService _inv;
public LoadController(IViewerRepository viewerRepository, IGlobalsRepository globalsRepository, public LoadController(IViewerRepository viewerRepository, IGlobalsRepository globalsRepository,
ICardAcquisitionService acquisition, IGameConfigService config, IGameConfigService config,
IBattlePassService battlePass, IViewerMissionStateService missionState, IBattlePassService battlePass, IViewerMissionStateService missionState,
SVSimDbContext db, IViewerEntitlements entitlements) SVSimDbContext db, IInventoryService inv)
{ {
_viewerRepository = viewerRepository; _viewerRepository = viewerRepository;
_globalsRepository = globalsRepository; _globalsRepository = globalsRepository;
_acquisition = acquisition;
_config = config; _config = config;
_battlePass = battlePass; _battlePass = battlePass;
_missionState = missionState; _missionState = missionState;
_db = db; _db = db;
_entitlements = entitlements; _inv = inv;
} }
[HttpPost("index")] [HttpPost("index")]
@@ -84,7 +83,9 @@ public class LoadController : SVSimController
// .AsNoTracking() — the local `viewer` instance is detached, and the service's writes // .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, // (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. // 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. // Lazy-materialize mission/achievement state. Idempotent — safe to call every /load/index.
await _missionState.EnsureCurrentAsync(viewer.Id); 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. // 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 // Owned-card projection (incl. the freeplay "all cards" path) lives in the entitlements
// service so both modes share one definition. // 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(); var classExpCurve = await _globalsRepository.GetClassExpCurve();
List<ClassExp> classExps = new(); List<ClassExp> classExps = new();
@@ -168,10 +169,10 @@ public class LoadController : SVSimController
UserInfo = new UserInfo(deviceType, viewer), UserInfo = new UserInfo(deviceType, viewer),
UserCurrency = new UserCurrency(viewer) UserCurrency = new UserCurrency(viewer)
{ {
Crystals = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Crystal), Crystals = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Crystal),
TotalCrystals = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Crystal), TotalCrystals = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Crystal),
Rupees = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.Rupee), Rupees = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.Rupee),
RedEther = (ulong)_entitlements.EffectiveBalance(viewer, SpendCurrency.RedEther), RedEther = (ulong)_inv.EffectiveBalance(viewer, SpendCurrency.RedEther),
}, },
UserItems = viewer.Items.Select(item => new UserItem(item)).ToList(), UserItems = viewer.Items.Select(item => new UserItem(item)).ToList(),
SpotPoint = checked((int)viewer.Currency.SpotPoints), SpotPoint = checked((int)viewer.Currency.SpotPoints),