feat(launcher): stabilize prepared content updates
This commit is contained in:
parent
f160f3fee1
commit
af9327a17b
42 changed files with 3706 additions and 147 deletions
|
|
@ -51,6 +51,9 @@ internal sealed record ContentEffectsAudioResult(
|
|||
internal sealed record ContentEffectsAudioDependencies(
|
||||
string DatDirectory,
|
||||
string PreparedAssetPath,
|
||||
string? PreparedAssetOverlayPath,
|
||||
uint? PreparedAssetBaseRecipeVersion,
|
||||
uint? PreparedAssetEffectiveRecipeVersion,
|
||||
ResidencyBudgetOptions ResidencyBudgets,
|
||||
PhysicsDataCache PhysicsDataCache,
|
||||
bool DumpMotionEnabled,
|
||||
|
|
@ -99,6 +102,9 @@ internal interface IContentEffectsAudioCompositionFactory
|
|||
IDatReaderWriter OpenDatCollection(string datDirectory);
|
||||
IPreparedAssetSource OpenPreparedAssetSource(
|
||||
string path,
|
||||
string? overlayPath,
|
||||
uint? baseRecipeVersion,
|
||||
uint? effectiveRecipeVersion,
|
||||
IDatReaderWriter dats,
|
||||
Action<string> diagnostic);
|
||||
MagicCatalog LoadMagicCatalog(IDatReaderWriter dats);
|
||||
|
|
@ -169,9 +175,54 @@ internal sealed class RetailContentEffectsAudioCompositionFactory
|
|||
|
||||
public IPreparedAssetSource OpenPreparedAssetSource(
|
||||
string path,
|
||||
string? overlayPath,
|
||||
uint? baseRecipeVersion,
|
||||
uint? effectiveRecipeVersion,
|
||||
IDatReaderWriter dats,
|
||||
Action<string> diagnostic) =>
|
||||
new PakPreparedAssetSource(path, dats, diagnostic);
|
||||
Action<string> diagnostic)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(overlayPath))
|
||||
{
|
||||
return new PakPreparedAssetSource(path, dats, diagnostic);
|
||||
}
|
||||
|
||||
if (baseRecipeVersion is not > 0
|
||||
|| effectiveRecipeVersion is not > 0)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
"Layered prepared content is missing its recipe identities.");
|
||||
}
|
||||
|
||||
if (effectiveRecipeVersion
|
||||
!= AcDream.Content.Pak.PakFormat.CurrentBakeToolVersion)
|
||||
{
|
||||
throw new InvalidDataException(
|
||||
$"Prepared content recipe {effectiveRecipeVersion} does not "
|
||||
+ $"match client recipe "
|
||||
+ $"{AcDream.Content.Pak.PakFormat.CurrentBakeToolVersion}.");
|
||||
}
|
||||
|
||||
PakPreparedAssetSource? baseSource = null;
|
||||
PakPreparedAssetSource? overlaySource = null;
|
||||
try
|
||||
{
|
||||
baseSource = new PakPreparedAssetSource(
|
||||
path,
|
||||
PreparedAssetCatalogIdentity.From(dats, baseRecipeVersion.Value),
|
||||
diagnostic);
|
||||
overlaySource = new PakPreparedAssetSource(
|
||||
overlayPath,
|
||||
PreparedAssetCatalogIdentity.From(dats, effectiveRecipeVersion.Value),
|
||||
diagnostic);
|
||||
return new LayeredPreparedAssetSource(baseSource, overlaySource);
|
||||
}
|
||||
catch
|
||||
{
|
||||
overlaySource?.Dispose();
|
||||
baseSource?.Dispose();
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public MagicCatalog LoadMagicCatalog(IDatReaderWriter dats) =>
|
||||
MagicCatalog.Load(dats);
|
||||
|
|
@ -370,6 +421,9 @@ internal sealed class ContentEffectsAudioCompositionPhase :
|
|||
"prepared asset source",
|
||||
() => _factory.OpenPreparedAssetSource(
|
||||
_dependencies.PreparedAssetPath,
|
||||
_dependencies.PreparedAssetOverlayPath,
|
||||
_dependencies.PreparedAssetBaseRecipeVersion,
|
||||
_dependencies.PreparedAssetEffectiveRecipeVersion,
|
||||
dats,
|
||||
_dependencies.Error),
|
||||
static value => value.Dispose()).Publish(
|
||||
|
|
|
|||
|
|
@ -71,6 +71,12 @@ internal sealed class SessionContentDescriptor
|
|||
|
||||
[JsonRequired]
|
||||
public string PreparedAssetPath { get; init; } = string.Empty;
|
||||
|
||||
public string? PreparedAssetOverlayPath { get; init; }
|
||||
|
||||
public uint? PreparedAssetBaseRecipeVersion { get; init; }
|
||||
|
||||
public uint? PreparedAssetEffectiveRecipeVersion { get; init; }
|
||||
}
|
||||
|
||||
internal sealed record SessionDescriptor
|
||||
|
|
|
|||
|
|
@ -83,6 +83,18 @@ internal static class SessionConfigurationLoader
|
|||
throw new SessionConfigurationException(
|
||||
"process.content requires non-empty datDirectory and preparedAssetPath.");
|
||||
}
|
||||
|
||||
bool hasOverlay = !string.IsNullOrWhiteSpace(
|
||||
content.PreparedAssetOverlayPath);
|
||||
bool hasBaseRecipe = content.PreparedAssetBaseRecipeVersion is > 0;
|
||||
bool hasEffectiveRecipe =
|
||||
content.PreparedAssetEffectiveRecipeVersion is > 0;
|
||||
if (hasOverlay != hasBaseRecipe || hasOverlay != hasEffectiveRecipe)
|
||||
{
|
||||
throw new SessionConfigurationException(
|
||||
"process.content overlay path, base recipe, and effective recipe "
|
||||
+ "must be supplied together.");
|
||||
}
|
||||
}
|
||||
|
||||
private static void ValidateSession(SessionDescriptor session)
|
||||
|
|
|
|||
|
|
@ -1418,6 +1418,9 @@ public sealed class GameWindow :
|
|||
new ContentEffectsAudioDependencies(
|
||||
_datDir,
|
||||
_options.PreparedAssetPath,
|
||||
_options.PreparedAssetOverlayPath,
|
||||
_options.PreparedAssetBaseRecipeVersion,
|
||||
_options.PreparedAssetEffectiveRecipeVersion,
|
||||
_options.ResidencyBudgets,
|
||||
_physicsDataCache,
|
||||
_animationDiagnostics.DumpMotionEnabled,
|
||||
|
|
|
|||
|
|
@ -116,6 +116,12 @@ public sealed record RuntimeOptions(
|
|||
/// <see cref="LoginCommands"/>, milliseconds.</summary>
|
||||
int LoginCommandDelayMs)
|
||||
{
|
||||
public string? PreparedAssetOverlayPath { get; init; }
|
||||
|
||||
public uint? PreparedAssetBaseRecipeVersion { get; init; }
|
||||
|
||||
public uint? PreparedAssetEffectiveRecipeVersion { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Build options from the process environment. Used by
|
||||
/// <c>Program.cs</c> at startup.
|
||||
|
|
@ -272,6 +278,12 @@ public sealed record RuntimeOptions(
|
|||
{
|
||||
PreparedAssetPath = NullIfEmpty(content?.PreparedAssetPath)
|
||||
?? baseOptions.PreparedAssetPath,
|
||||
PreparedAssetOverlayPath =
|
||||
NullIfEmpty(content?.PreparedAssetOverlayPath),
|
||||
PreparedAssetBaseRecipeVersion =
|
||||
content?.PreparedAssetBaseRecipeVersion,
|
||||
PreparedAssetEffectiveRecipeVersion =
|
||||
content?.PreparedAssetEffectiveRecipeVersion,
|
||||
LiveMode = true,
|
||||
// Campaign LA gate round 2: a session-config launch IS a product
|
||||
// launch — the retail UI is the shipped UI, not a dev option.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue