From 9043e206467da629c45ac465257449984f5df5d7 Mon Sep 17 00:00:00 2001 From: gamer147 Date: Tue, 26 May 2026 22:49:30 -0400 Subject: [PATCH] feat(bp): IBattlePassService skeleton + level-curve method + DI --- .../Models/Dtos/BattlePassLevel.cs | 11 ++++++-- SVSim.EmulatedEntrypoint/Program.cs | 6 ++++ .../Services/BattlePassBuyOutcome.cs | 14 ++++++++++ .../Services/BattlePassPointGrant.cs | 17 +++++++++++ .../Services/BattlePassPointSource.cs | 12 ++++++++ .../Services/BattlePassService.cs | 28 +++++++++++++++++++ .../Services/IBattlePassService.cs | 11 ++++++++ 7 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 SVSim.EmulatedEntrypoint/Services/BattlePassBuyOutcome.cs create mode 100644 SVSim.EmulatedEntrypoint/Services/BattlePassPointGrant.cs create mode 100644 SVSim.EmulatedEntrypoint/Services/BattlePassPointSource.cs create mode 100644 SVSim.EmulatedEntrypoint/Services/BattlePassService.cs create mode 100644 SVSim.EmulatedEntrypoint/Services/IBattlePassService.cs diff --git a/SVSim.EmulatedEntrypoint/Models/Dtos/BattlePassLevel.cs b/SVSim.EmulatedEntrypoint/Models/Dtos/BattlePassLevel.cs index 23a1c00..e878f43 100644 --- a/SVSim.EmulatedEntrypoint/Models/Dtos/BattlePassLevel.cs +++ b/SVSim.EmulatedEntrypoint/Models/Dtos/BattlePassLevel.cs @@ -3,13 +3,18 @@ using System.Text.Json.Serialization; namespace SVSim.EmulatedEntrypoint.Models.Dtos; +/// +/// One entry under /load/index.battle_pass_level_info. Per memory +/// project_wire_key_serialization, wire ints are strings here — client parses them via .ToInt(). +/// [MessagePackObject] public class BattlePassLevel { [JsonPropertyName("level")] [Key("level")] - public int Level { get; set; } + public string Level { get; set; } = ""; + [JsonPropertyName("required_point")] [Key("required_point")] - public int RequiredPoints { get; set; } -} \ No newline at end of file + public string RequiredPoint { get; set; } = ""; +} diff --git a/SVSim.EmulatedEntrypoint/Program.cs b/SVSim.EmulatedEntrypoint/Program.cs index 6e6c187..8d06003 100644 --- a/SVSim.EmulatedEntrypoint/Program.cs +++ b/SVSim.EmulatedEntrypoint/Program.cs @@ -83,6 +83,12 @@ public class Program builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddScoped(); + builder.Services.AddSingleton(TimeProvider.System); builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/SVSim.EmulatedEntrypoint/Services/BattlePassBuyOutcome.cs b/SVSim.EmulatedEntrypoint/Services/BattlePassBuyOutcome.cs new file mode 100644 index 0000000..5d7060f --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/BattlePassBuyOutcome.cs @@ -0,0 +1,14 @@ +using SVSim.Database.Services; + +namespace SVSim.EmulatedEntrypoint.Services; + +/// +/// Result of . AchievedRewards = the +/// delta that was just granted (goes into achieved_info.battle_pass_reward_list); +/// PostStateTotals = post-state totals for affected goods (goes into reward_list), +/// including the crystal deduction per memory project_wire_reward_list_post_state. +/// +public sealed record BattlePassBuyOutcome( + int ResultCode, + IReadOnlyList AchievedRewards, + IReadOnlyList PostStateTotals); diff --git a/SVSim.EmulatedEntrypoint/Services/BattlePassPointGrant.cs b/SVSim.EmulatedEntrypoint/Services/BattlePassPointGrant.cs new file mode 100644 index 0000000..686d7ea --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/BattlePassPointGrant.cs @@ -0,0 +1,17 @@ +using SVSim.Database.Services; + +namespace SVSim.EmulatedEntrypoint.Services; + +/// +/// Result of . Future point-source endpoints +/// (mission/retire, battle finish handlers) translate this into the embedded +/// battle_pass_gauge_info block on their response. +/// +public sealed record BattlePassPointGrant( + int BeforePoint, + int BeforeLevel, + int AfterPoint, + int AfterLevel, + int PointAdd, + BattlePassPointSource Source, + IReadOnlyList NewlyClaimed); diff --git a/SVSim.EmulatedEntrypoint/Services/BattlePassPointSource.cs b/SVSim.EmulatedEntrypoint/Services/BattlePassPointSource.cs new file mode 100644 index 0000000..9765cf1 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/BattlePassPointSource.cs @@ -0,0 +1,12 @@ +namespace SVSim.EmulatedEntrypoint.Services; + +/// +/// Which categorized field on battle_pass_gauge_info a point grant feeds. Mirrors the +/// breakdown shown by BattlePassResultPanel after a win. +/// +public enum BattlePassPointSource +{ + BattleResult, + DailyMission, + BattlePassMission, +} diff --git a/SVSim.EmulatedEntrypoint/Services/BattlePassService.cs b/SVSim.EmulatedEntrypoint/Services/BattlePassService.cs new file mode 100644 index 0000000..061049e --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/BattlePassService.cs @@ -0,0 +1,28 @@ +using System.Globalization; +using SVSim.Database.Repositories.BattlePass; +using SVSim.EmulatedEntrypoint.Models.Dtos; + +namespace SVSim.EmulatedEntrypoint.Services; + +public sealed class BattlePassService : IBattlePassService +{ + private readonly IBattlePassRepository _bp; + + public BattlePassService(IBattlePassRepository bp) + { + _bp = bp; + } + + public async Task?> GetLevelCurveAsync(CancellationToken ct) + { + var rows = await _bp.GetLevelCurveAsync(ct); + if (rows.Count == 0) return null; + return rows.ToDictionary( + r => r.Level.ToString(CultureInfo.InvariantCulture), + r => new BattlePassLevel + { + Level = r.Level.ToString(CultureInfo.InvariantCulture), + RequiredPoint = r.RequiredPoint.ToString(CultureInfo.InvariantCulture), + }); + } +} diff --git a/SVSim.EmulatedEntrypoint/Services/IBattlePassService.cs b/SVSim.EmulatedEntrypoint/Services/IBattlePassService.cs new file mode 100644 index 0000000..5aa0637 --- /dev/null +++ b/SVSim.EmulatedEntrypoint/Services/IBattlePassService.cs @@ -0,0 +1,11 @@ +using SVSim.EmulatedEntrypoint.Models.Dtos; + +namespace SVSim.EmulatedEntrypoint.Services; + +public interface IBattlePassService +{ + /// Global level curve as wire-string dictionary; null if no levels seeded. + Task?> GetLevelCurveAsync(CancellationToken ct); + + // The Info / ItemList / Buy / AddPoints methods are added in later tasks (11, 12, 13, 14). +}