A wiped/fresh client (NukeIdentityOnStartup, new install, or any path that clears PlayerPrefs) defaults its stored RES_VER to "00000000" per Cute/SavedataManager.GetResourceVersion. The client builds the Akamai manifest URL as dl/Manifest/<RES_VER>/<lang>/<Platform>/, and Akamai 404s the "00000000" path -> Toolbox.AssetManager.InitializeManifest fails -> the title screen shows "Connection Error / Reconnect" before any tutorial UI loads. Fix: - New ResourceConfig [ConfigSection] in SVSim.Database — single field RequiredResVer defaulting to "4670rPsPMVlRTd2" (the value prod returned in data_dumps/traffic_prod_tutorial.ndjson and was still returning at 2026-05-28 21:00 UTC). Lives in GameConfigs so it can be tuned via DB / appsettings without code edits. - ShadowverseTranslationMiddleware injects IGameConfigService and emits required_res_ver in data_headers ONLY on /check/game_start responses. NetworkTask.Parse opens a "new data is available" popup whenever required_res_ver is present and the URL is anything other than GameStartCheck (NetworkTask.cs:128-138); the suppression on game_start is what lets us silently bump PlayerPrefs["RES_VER"] before ResourceDownloader runs. - DataHeaders gains a nullable RequiredResVer field. DataWrapper.DataHeaders is now Dictionary<string, object?> instead of the typed DataHeaders POCO directly — the construction site stays type-safe (the middleware builds the typed POCO, then projects through the same STJ + ConvertJsonTreeToPlainObject pipeline that DataWrapper.Data uses) so null-valued optional fields are absent from the wire instead of being written as "key":null. Without this, MessagePack's ContractlessStandardResolver walked the typed properties and wrote required_res_ver=null on every non-game_start response, tripping the popup on every boot. - GameConfigurationJsonbTests updated to expect the 9th config section. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
38 lines
2.0 KiB
C#
38 lines
2.0 KiB
C#
namespace SVSim.Database.Models.Config;
|
|
|
|
/// <summary>
|
|
/// Asset-delivery tunables: where the client looks for the resource CDN (Akamai by default;
|
|
/// <c>Wizard/SetUp.cs:48</c> hardcodes <c>shadowverse.akamaized.net/</c>) and what manifest
|
|
/// version to ask for. Currently a single field, will grow as we self-host content.
|
|
/// </summary>
|
|
[ConfigSection("ResourceConfig")]
|
|
public class ResourceConfig
|
|
{
|
|
/// <summary>
|
|
/// Pushed to the client as <c>data_headers.required_res_ver</c>. The client writes it to
|
|
/// <c>PlayerPrefs["RES_VER"]</c> and uses it as the version path component for asset
|
|
/// manifest lookups: <c>https://<cdn>/dl/Manifest/<RES_VER>/<lang>/<Platform>/</c>.
|
|
/// <para>
|
|
/// Default value is the prod-captured version from <c>data_dumps/traffic_prod_tutorial.ndjson</c>
|
|
/// (2026-05-28) — i.e., a path Akamai actually serves. When this rotates (or Akamai sunsets
|
|
/// ahead of June 2026), update via DB <c>GameConfigs</c> row, appsettings.json, or this
|
|
/// shipped default; no code change needed.
|
|
/// </para>
|
|
/// <para>
|
|
/// When the client has no cached <c>RES_VER</c> (e.g., a wiped/fresh install via
|
|
/// <c>NukeIdentityOnStartup</c>), it defaults to <c>"00000000"</c>, which Akamai 404s. The
|
|
/// fetch failure surfaces as "Connection Error / Reconnect" before any tutorial UI loads,
|
|
/// so emitting a valid value here is required for fresh-account boot.
|
|
/// </para>
|
|
/// </summary>
|
|
public string RequiredResVer { get; set; } = "4670rPsPMVlRTd2";
|
|
|
|
/// <summary>
|
|
/// Inline-default tier for <see cref="IGameConfigService"/>. Mirrors property initialisers
|
|
/// — kept as a separate factory because the framework requires every [ConfigSection] POCO to
|
|
/// expose one (see <c>feedback_config_defaults</c> memory for the collection-defaults rule
|
|
/// that motivated the convention).
|
|
/// </summary>
|
|
public static ResourceConfig ShippedDefaults() => new();
|
|
}
|