Class leader fixes
This commit is contained in:
@@ -68,7 +68,6 @@ public class GlobalsImporter
|
||||
if (deckInfo.HasValue)
|
||||
{
|
||||
total += await ImportDefaultDecks(context, deckInfo.Value);
|
||||
total += await ImportDefaultLeaderSkinSettings(context, deckInfo.Value);
|
||||
}
|
||||
|
||||
if (paymentItemList.HasValue)
|
||||
@@ -716,28 +715,6 @@ public class GlobalsImporter
|
||||
return created + updated;
|
||||
}
|
||||
|
||||
// ---------- Deck/info: Default Leader Skin Settings ----------
|
||||
|
||||
private async Task<int> ImportDefaultLeaderSkinSettings(SVSimDbContext context, JsonElement deckInfo)
|
||||
{
|
||||
if (!deckInfo.TryGetProperty("user_leader_skin_setting_list", out var info) || info.ValueKind != JsonValueKind.Object) return 0;
|
||||
|
||||
var existing = await context.DefaultLeaderSkinSettings.ToDictionaryAsync(e => e.Id);
|
||||
int created = 0, updated = 0;
|
||||
foreach (var kv in info.EnumerateObject())
|
||||
{
|
||||
if (!int.TryParse(kv.Name, out int classId)) continue;
|
||||
var v = kv.Value;
|
||||
var entry = existing.TryGetValue(classId, out var ex) ? ex : new DefaultLeaderSkinSettingEntry { Id = classId };
|
||||
entry.IsRandomLeaderSkin = GetInt(v, "is_random_leader_skin");
|
||||
entry.LeaderSkinId = GetInt(v, "leader_skin_id");
|
||||
if (ex is null) { context.DefaultLeaderSkinSettings.Add(entry); created++; }
|
||||
else updated++;
|
||||
}
|
||||
Console.WriteLine($"[GlobalsImporter] DefaultLeaderSkinSettings: +{created}/~{updated}");
|
||||
return created + updated;
|
||||
}
|
||||
|
||||
// ---------- Payment: Item list (Steam/PC storefront, dict-keyed by store_product_id) ----------
|
||||
|
||||
private async Task<int> ImportPaymentItems(SVSimDbContext context, JsonElement payment)
|
||||
|
||||
2809
SVSim.Database/Migrations/20260526132106_DropDefaultLeaderSkinSettings.Designer.cs
generated
Normal file
2809
SVSim.Database/Migrations/20260526132106_DropDefaultLeaderSkinSettings.Designer.cs
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,38 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
|
||||
#nullable disable
|
||||
|
||||
namespace SVSim.Database.Migrations
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public partial class DropDefaultLeaderSkinSettings : Migration
|
||||
{
|
||||
/// <inheritdoc />
|
||||
protected override void Up(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.DropTable(
|
||||
name: "DefaultLeaderSkinSettings");
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void Down(MigrationBuilder migrationBuilder)
|
||||
{
|
||||
migrationBuilder.CreateTable(
|
||||
name: "DefaultLeaderSkinSettings",
|
||||
columns: table => new
|
||||
{
|
||||
Id = table.Column<int>(type: "integer", nullable: false),
|
||||
ClassId = table.Column<int>(type: "integer", nullable: false),
|
||||
DateCreated = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||
DateUpdated = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||
IsRandomLeaderSkin = table.Column<int>(type: "integer", nullable: false),
|
||||
LeaderSkinId = table.Column<int>(type: "integer", nullable: false)
|
||||
},
|
||||
constraints: table =>
|
||||
{
|
||||
table.PrimaryKey("PK_DefaultLeaderSkinSettings", x => x.Id);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,31 +824,6 @@ namespace SVSim.Database.Migrations
|
||||
b.ToTable("DefaultDecks");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Models.DefaultLeaderSkinSettingEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("ClassId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<DateTime>("DateCreated")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<DateTime?>("DateUpdated")
|
||||
.HasColumnType("timestamp with time zone");
|
||||
|
||||
b.Property<int>("IsRandomLeaderSkin")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.Property<int>("LeaderSkinId")
|
||||
.HasColumnType("integer");
|
||||
|
||||
b.HasKey("Id");
|
||||
|
||||
b.ToTable("DefaultLeaderSkinSettings");
|
||||
});
|
||||
|
||||
modelBuilder.Entity("SVSim.Database.Models.DegreeEntry", b =>
|
||||
{
|
||||
b.Property<int>("Id")
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
using SVSim.Database.Common;
|
||||
|
||||
namespace SVSim.Database.Models;
|
||||
|
||||
/// <summary>One row per class: which leader skin is default and whether random rotation is on.</summary>
|
||||
public class DefaultLeaderSkinSettingEntry : BaseEntity<int>
|
||||
{
|
||||
public int ClassId { get => Id; set => Id = value; }
|
||||
|
||||
public int IsRandomLeaderSkin { get; set; }
|
||||
|
||||
public int LeaderSkinId { get; set; }
|
||||
}
|
||||
@@ -41,9 +41,6 @@ public class GlobalsRepository : IGlobalsRepository
|
||||
public Task<List<DefaultDeckEntry>> GetDefaultDecks() =>
|
||||
_dbContext.DefaultDecks.AsNoTracking().ToListAsync();
|
||||
|
||||
public Task<List<DefaultLeaderSkinSettingEntry>> GetDefaultLeaderSkinSettings() =>
|
||||
_dbContext.DefaultLeaderSkinSettings.AsNoTracking().ToListAsync();
|
||||
|
||||
public Task<ArenaSeasonConfig?> GetCurrentArenaSeason() =>
|
||||
_dbContext.ArenaSeasons.AsNoTracking().FirstOrDefaultAsync(e => e.Id == 1);
|
||||
|
||||
|
||||
@@ -13,7 +13,6 @@ public interface IGlobalsRepository
|
||||
Task<List<MyRotationAbilityEntry>> GetMyRotationAbilities();
|
||||
Task<List<AvatarAbilityEntry>> GetAvatarAbilities();
|
||||
Task<List<DefaultDeckEntry>> GetDefaultDecks();
|
||||
Task<List<DefaultLeaderSkinSettingEntry>> GetDefaultLeaderSkinSettings();
|
||||
Task<ArenaSeasonConfig?> GetCurrentArenaSeason();
|
||||
Task<List<SpotCardEntry>> GetSpotCards();
|
||||
Task<List<ReprintedCardEntry>> GetReprintedCards();
|
||||
|
||||
@@ -44,7 +44,6 @@ public class SVSimDbContext : DbContext
|
||||
public DbSet<MyRotationAbilityEntry> MyRotationAbilities => Set<MyRotationAbilityEntry>();
|
||||
public DbSet<AvatarAbilityEntry> AvatarAbilities => Set<AvatarAbilityEntry>();
|
||||
public DbSet<DefaultDeckEntry> DefaultDecks => Set<DefaultDeckEntry>();
|
||||
public DbSet<DefaultLeaderSkinSettingEntry> DefaultLeaderSkinSettings => Set<DefaultLeaderSkinSettingEntry>();
|
||||
public DbSet<ArenaSeasonConfig> ArenaSeasons => Set<ArenaSeasonConfig>();
|
||||
public DbSet<SpotCardEntry> SpotCards => Set<SpotCardEntry>();
|
||||
public DbSet<ReprintedCardEntry> ReprintedCards => Set<ReprintedCardEntry>();
|
||||
|
||||
@@ -125,7 +125,7 @@ public class DeckController : SVSimController
|
||||
}),
|
||||
UserLeaderSkinSettingList = viewerClasses.ToDictionary(
|
||||
vc => vc.Id.ToString(),
|
||||
vc => new DefaultLeaderSkinSetting
|
||||
vc => new UserLeaderSkinSetting
|
||||
{
|
||||
ClassId = vc.Id,
|
||||
IsRandomLeaderSkin = 0, // random-skin mode (per-class shuffle pool) not yet persisted
|
||||
|
||||
@@ -46,10 +46,11 @@ public class DeckListResponse
|
||||
[Key("default_deck_list")] public Dictionary<string, DefaultDeck> DefaultDeckList { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Default leader skin per class, keyed by class_id as string.
|
||||
/// Per-class leader skin setting (active skin id) for the requesting viewer, keyed by
|
||||
/// class_id as string.
|
||||
/// </summary>
|
||||
[JsonPropertyName("user_leader_skin_setting_list")]
|
||||
[Key("user_leader_skin_setting_list")] public Dictionary<string, DefaultLeaderSkinSetting> UserLeaderSkinSettingList { get; set; } = new();
|
||||
[Key("user_leader_skin_setting_list")] public Dictionary<string, UserLeaderSkinSetting> UserLeaderSkinSettingList { get; set; } = new();
|
||||
|
||||
/// <summary>
|
||||
/// Trial / tutorial-specific decks. Prod emits this on <c>/deck/info</c> (All format) but
|
||||
|
||||
@@ -4,12 +4,13 @@ using System.Text.Json.Serialization;
|
||||
namespace SVSim.EmulatedEntrypoint.Models.Dtos;
|
||||
|
||||
/// <summary>
|
||||
/// Default leader skin per class (8 entries — one per class). Surfaced under
|
||||
/// <c>/deck/info data.user_leader_skin_setting_list</c>. Despite the <c>user_</c> prefix on the
|
||||
/// wire, this is GLOBAL data (same for every viewer) — naming is the client's, not ours.
|
||||
/// Per-class entry of <c>/deck/info data.user_leader_skin_setting_list</c>. Per-viewer state:
|
||||
/// each viewer's class-level "active leader skin" preference, used as a fallback when a deck
|
||||
/// has <c>leader_skin_id == 0</c>. Sourced from <c>ViewerClassData.LeaderSkin</c>; mutated by
|
||||
/// <c>POST /leader_skin/set</c>.
|
||||
/// </summary>
|
||||
[MessagePackObject]
|
||||
public class DefaultLeaderSkinSetting
|
||||
public class UserLeaderSkinSetting
|
||||
{
|
||||
[JsonPropertyName("class_id")]
|
||||
[Key("class_id")]
|
||||
@@ -197,14 +197,11 @@ public class GlobalsRepositoryTests
|
||||
"Each starter deck should serialize multiple card IDs in card_id_array.");
|
||||
}
|
||||
|
||||
[Test]
|
||||
public async Task GetDefaultLeaderSkinSettings_returns_8_entries()
|
||||
{
|
||||
var (factory, repo) = await SetupAsync();
|
||||
using var _ = factory;
|
||||
var skins = await repo.GetDefaultLeaderSkinSettings();
|
||||
Assert.That(skins.Count, Is.EqualTo(8));
|
||||
}
|
||||
// Note: GetDefaultLeaderSkinSettings was removed from IGlobalsRepository in the
|
||||
// 2026-05-26 per-viewer leader-skin refactor. /deck/info now sources
|
||||
// user_leader_skin_setting_list from viewer.Classes (each ViewerClassData carries the
|
||||
// active LeaderSkin), and /leader_skin/set mutates it. Coverage moved to
|
||||
// LeaderSkinControllerTests.
|
||||
|
||||
// Note: GetGameConfiguration was removed from IGlobalsRepository in the 2026-05-24 config
|
||||
// refactor — Rotation/Challenge/etc. now load via IGameConfigService. See
|
||||
|
||||
Reference in New Issue
Block a user