diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index b43ddf6..8c2061c 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -8,7 +8,7 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
- interval: "daily"
+ interval: "weekly"
groups:
actions-deps:
patterns:
@@ -19,7 +19,7 @@ updates:
- package-ecosystem: "nuget"
directory: "/"
schedule:
- interval: "daily"
+ interval: "weekly"
target-branch: "develop"
open-pull-requests-limit: 1
groups:
diff --git a/.gitignore b/.gitignore
index 8a30d25..7d20657 100644
--- a/.gitignore
+++ b/.gitignore
@@ -396,3 +396,6 @@ FodyWeavers.xsd
# JetBrains Rider
*.sln.iml
+.idea
+
+.local_deploy
\ No newline at end of file
diff --git a/Directory.Build.props b/Directory.Build.props
index d475e7f..5110cdb 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -12,7 +12,7 @@
ModVerify
Alamo Engine Tools and Contributors
- Copyright © 2025 Alamo Engine Tools and contributors. All rights reserved.
+ Copyright © 2026 Alamo Engine Tools and contributors. All rights reserved.
https://github.com/AlamoEngine-Tools/ModVerify
$(RepoRootPath)LICENSE
MIT
@@ -33,7 +33,7 @@
-
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/LICENSE b/LICENSE
index 7159126..23fe869 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
MIT License
-Copyright (c) 2024 Alamo Engine Tools
+Copyright (c) 2026 Alamo Engine Tools
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
diff --git a/deploy-local.ps1 b/deploy-local.ps1
new file mode 100644
index 0000000..740c579
--- /dev/null
+++ b/deploy-local.ps1
@@ -0,0 +1,75 @@
+# Local deployment script for ModVerify to test the update feature.
+# This script builds the application, creates an update manifest, and "deploys" it to a local directory.
+
+$ErrorActionPreference = "Stop"
+
+$root = $PSScriptRoot
+if ([string]::IsNullOrEmpty($root)) { $root = Get-Location }
+
+$deployRoot = Join-Path $root ".local_deploy"
+$stagingDir = Join-Path $deployRoot "staging"
+$serverDir = Join-Path $deployRoot "server"
+$installDir = Join-Path $deployRoot "install"
+
+$toolProj = Join-Path $root "src\ModVerify.CliApp\ModVerify.CliApp.csproj"
+$creatorProj = Join-Path $root "modules\ModdingToolBase\src\AnakinApps\ApplicationManifestCreator\ApplicationManifestCreator.csproj"
+$uploaderProj = Join-Path $root "modules\ModdingToolBase\src\AnakinApps\FtpUploader\FtpUploader.csproj"
+
+$toolExe = "ModVerify.exe"
+$updaterExe = "AnakinRaW.ExternalUpdater.exe"
+$manifestCreatorDll = "AnakinRaW.ApplicationManifestCreator.dll"
+$uploaderDll = "AnakinRaW.FtpUploader.dll"
+
+# 1. Clean and Create directories
+if (Test-Path $deployRoot) { Remove-Item -Recurse -Force $deployRoot }
+New-Item -ItemType Directory -Path $stagingDir | Out-Null
+New-Item -ItemType Directory -Path $serverDir | Out-Null
+New-Item -ItemType Directory -Path $installDir | Out-Null
+
+Write-Host "--- Building ModVerify (net481) ---" -ForegroundColor Cyan
+dotnet build $toolProj --configuration Release -f net481 --output "$deployRoot\bin\tool" /p:DebugType=None /p:DebugSymbols=false
+
+Write-Host "--- Building Manifest Creator ---" -ForegroundColor Cyan
+dotnet build $creatorProj --configuration Release --output "$deployRoot\bin\creator"
+
+Write-Host "--- Building Local Uploader ---" -ForegroundColor Cyan
+dotnet build $uploaderProj --configuration Release --output "$deployRoot\bin\uploader"
+
+# 2. Prepare staging
+Write-Host "--- Preparing Staging ---" -ForegroundColor Cyan
+Copy-Item "$deployRoot\bin\tool\$toolExe" $stagingDir
+Copy-Item "$deployRoot\bin\tool\$updaterExe" $stagingDir
+
+# 3. Create Manifest
+# Origin must be an absolute URI for the manifest creator.
+# Using 127.0.0.1 and file:// is tricky with Flurl/DownloadManager sometimes.
+# We'll use the local path and ensure it's formatted correctly.
+$serverPath = (Resolve-Path $serverDir).Path
+$serverUri = "file:///$($serverPath.Replace('\', '/'))"
+# If we have 3 slashes, Flurl/DownloadManager might still fail on Windows if it expects a certain format.
+# However, the ManifestCreator just needs a valid URI for the 'Origin' field in the manifest.
+Write-Host "--- Creating Manifest (Origin: $serverUri) ---" -ForegroundColor Cyan
+dotnet "$deployRoot\bin\creator\$manifestCreatorDll" `
+ -a "$stagingDir\$toolExe" `
+ --appDataFiles "$stagingDir\$updaterExe" `
+ --origin "$serverUri" `
+ -o "$stagingDir" `
+ -b "beta"
+
+# 4. "Deploy" to server using the local uploader
+Write-Host "--- Deploying to Local Server ---" -ForegroundColor Cyan
+dotnet "$deployRoot\bin\uploader\$uploaderDll" local --base "$serverDir" --source "$stagingDir"
+
+# 5. Setup a "test" installation
+Write-Host "--- Setting up Test Installation ---" -ForegroundColor Cyan
+Copy-Item "$deployRoot\bin\tool\*" $installDir -Recurse
+
+Write-Host "`nLocal deployment complete!" -ForegroundColor Green
+Write-Host "Server directory: $serverDir"
+Write-Host "Install directory: $installDir"
+Write-Host "`nTo test the update:"
+Write-Host "1. (Optional) Modify the version in version.json and run this script again to 'push' a new version to the local server."
+Write-Host "2. Run ModVerify from the install directory with the following command:"
+Write-Host " cd '$installDir'"
+Write-Host " .\ModVerify.exe updateApplication --updateManifestUrl '$serverUri'"
+Write-Host "`n Note: You can also specify a different branch using --updateBranch if needed."
diff --git a/modules/ModdingToolBase b/modules/ModdingToolBase
index 479a088..3552005 160000
--- a/modules/ModdingToolBase
+++ b/modules/ModdingToolBase
@@ -1 +1 @@
-Subproject commit 479a088a2b26dd4a3e2342b2e34f5359b0252e88
+Subproject commit 3552005cbaa2b7199698924d17786550e370f7ba
diff --git a/src/ModVerify.CliApp/GameFinder/GameFinderService.cs b/src/ModVerify.CliApp/GameFinder/GameFinderService.cs
index a88ebd9..aca0533 100644
--- a/src/ModVerify.CliApp/GameFinder/GameFinderService.cs
+++ b/src/ModVerify.CliApp/GameFinder/GameFinderService.cs
@@ -1,9 +1,11 @@
using System;
using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.IO.Abstractions;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
+using PG.StarWarsGame.Engine;
using PG.StarWarsGame.Infrastructure.Clients.Steam;
using PG.StarWarsGame.Infrastructure.Games;
using PG.StarWarsGame.Infrastructure.Mods;
@@ -12,6 +14,17 @@
namespace AET.ModVerify.App.GameFinder;
+internal class GameFinderSettings
+{
+ internal static readonly GameFinderSettings Default = new();
+
+ public bool InitMods { get; init; } = true;
+
+ public bool SearchFallbackGame { get; init; } = true;
+
+ public GameEngineType? Engine { get; init; } = null;
+}
+
internal class GameFinderService
{
private readonly IServiceProvider _serviceProvider;
@@ -29,7 +42,7 @@ public GameFinderService(IServiceProvider serviceProvider)
_logger = _serviceProvider.GetService()?.CreateLogger(GetType());
}
- public GameFinderResult FindGames()
+ public GameFinderResult FindGames(GameFinderSettings settings)
{
var detectors = new List
{
@@ -37,10 +50,38 @@ public GameFinderResult FindGames()
new SteamPetroglyphStarWarsGameDetector(_serviceProvider),
};
- return FindGames(detectors);
+ return FindGames(detectors, settings);
+ }
+
+ public IGame FindGame(string gamePath, GameFinderSettings settings)
+ {
+ var detectors = new List
+ {
+ new DirectoryGameDetector(_fileSystem.DirectoryInfo.New(gamePath), _serviceProvider),
+ };
+ return FindGames(detectors, settings).Game;
}
- public GameFinderResult FindGamesFromPathOrGlobal(string path)
+ public bool TryFindGame(string gamePath, GameFinderSettings settings, [NotNullWhen(true)]out IGame? game)
+ {
+ var detectors = new List
+ {
+ new DirectoryGameDetector(_fileSystem.DirectoryInfo.New(gamePath), _serviceProvider),
+ };
+
+ try
+ {
+ game = FindGames(detectors, settings).Game;
+ return true;
+ }
+ catch (GameNotFoundException)
+ {
+ game = null;
+ return false;
+ }
+ }
+
+ public GameFinderResult FindGamesFromPathOrGlobal(string path, GameFinderSettings settings)
{
// There are four common situations:
// 1. path points to the actual game directory
@@ -62,55 +103,55 @@ public GameFinderResult FindGamesFromPathOrGlobal(string path)
// Cases 3 & 4
detectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider));
- return FindGames(detectors);
+ return FindGames(detectors, settings);
}
-
- private bool TryDetectGame(GameType gameType, IList detectors, out GameDetectionResult result)
+
+ private GameFinderResult FindGames(IList detectors, GameFinderSettings settings)
{
- var gd = new CompositeGameDetector(detectors, _serviceProvider);
-
- try
+ GameDetectionResult? detectionResult = null;
+ if (settings.Engine is GameEngineType.Eaw)
{
- result = gd.Detect(gameType);
- if (result.GameLocation is null)
- return false;
- return true;
+ _logger?.LogTrace("Trying to find requested EaW installation.");
+ if (!TryDetectGame(GameType.Eaw, detectors, out detectionResult))
+ {
+ var e = new GameNotFoundException($"Unable to find requested game installation '{settings.Engine}'. Wrong install path?");
+ _logger?.LogTrace(e, e.Message);
+ throw e;
+ }
}
- catch (Exception e)
- {
- result = GameDetectionResult.NotInstalled(gameType);
- _logger?.LogTrace("Unable to find game installation: {Message}", e.Message);
- return false;
- }
- }
-
- private GameFinderResult FindGames(IList detectors)
- {
- // FoC needs to be tried first
- if (!TryDetectGame(GameType.Foc, detectors, out var result))
+
+ if (detectionResult is null && !TryDetectGame(GameType.Foc, detectors, out detectionResult))
{
+ if (settings.Engine is GameEngineType.Foc)
+ {
+ var e = new GameNotFoundException($"Unable to find requested game installation '{settings.Engine}'. Wrong install path?");
+ _logger?.LogTrace(e, e.Message);
+ throw e;
+ }
+
+ // If the engine is unspecified, we also need to check for EaW.
_logger?.LogTrace("Unable to find FoC installation. Trying again with EaW...");
- if (!TryDetectGame(GameType.Eaw, detectors, out result))
+ if (!TryDetectGame(GameType.Eaw, detectors, out detectionResult))
throw new GameNotFoundException("Unable to find game installation: Wrong install path?");
}
- if (result.GameLocation is null)
+ if (detectionResult.GameLocation is null)
throw new GameNotFoundException("Unable to find game installation: Wrong install path?");
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
- "Found game installation: {ResultGameIdentity} at {GameLocationFullName}", result.GameIdentity, result.GameLocation.FullName);
+ "Found game installation: {ResultGameIdentity} at {GameLocationFullName}", detectionResult.GameIdentity, detectionResult.GameLocation.FullName);
- var game = _gameFactory.CreateGame(result, CultureInfo.InvariantCulture);
+ var game = _gameFactory.CreateGame(detectionResult, CultureInfo.InvariantCulture);
- SetupMods(game);
+ if (settings.InitMods)
+ SetupMods(game);
IGame? fallbackGame = null;
- // If the game is Foc we want to set up Eaw as well as the fallbackGame
- if (game.Type == GameType.Foc)
+ if (SearchForFallbackGame(settings, detectionResult))
{
var fallbackDetectors = new List();
-
+
if (game.Platform == GamePlatform.SteamGold)
fallbackDetectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider));
else
@@ -119,17 +160,46 @@ private GameFinderResult FindGames(IList detectors)
if (!TryDetectGame(GameType.Eaw, fallbackDetectors, out var fallbackResult) || fallbackResult.GameLocation is null)
throw new GameNotFoundException("Unable to find fallback game installation: Wrong install path?");
- _logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
+ _logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
"Found fallback game installation: {FallbackResultGameIdentity} at {GameLocationFullName}", fallbackResult.GameIdentity, fallbackResult.GameLocation.FullName);
fallbackGame = _gameFactory.CreateGame(fallbackResult, CultureInfo.InvariantCulture);
- SetupMods(fallbackGame);
+ if (settings.InitMods)
+ SetupMods(fallbackGame);
}
return new GameFinderResult(game, fallbackGame);
}
+ private static bool SearchForFallbackGame(GameFinderSettings settings, GameDetectionResult? foundGame)
+ {
+ if (settings.Engine is GameEngineType.Eaw)
+ return false;
+ if (foundGame is { Installed: true, GameIdentity.Type: GameType.Eaw })
+ return false;
+ return settings.SearchFallbackGame;
+ }
+
+ private bool TryDetectGame(GameType gameType, IList detectors, out GameDetectionResult result)
+ {
+ var gd = new CompositeGameDetector(detectors, _serviceProvider);
+
+ try
+ {
+ result = gd.Detect(gameType);
+ if (result.GameLocation is null)
+ return false;
+ return true;
+ }
+ catch (Exception e)
+ {
+ result = GameDetectionResult.NotInstalled(gameType);
+ _logger?.LogTrace("Unable to find game installation: {Message}", e.Message);
+ return false;
+ }
+ }
+
private void SetupMods(IGame game)
{
var modFinder = _serviceProvider.GetRequiredService();
diff --git a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs
deleted file mode 100644
index 717db7b..0000000
--- a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using System;
-using System.Globalization;
-using System.IO.Abstractions;
-using System.Linq;
-using AET.ModVerify.App.GameFinder;
-using AET.ModVerify.App.Settings;
-using AET.ModVerify.App.Utilities;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Infrastructure;
-using PG.StarWarsGame.Infrastructure.Games;
-using PG.StarWarsGame.Infrastructure.Mods;
-using PG.StarWarsGame.Infrastructure.Services;
-using PG.StarWarsGame.Infrastructure.Services.Detection;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal class AutomaticModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider)
-{
- private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService();
-
- public override GameLocations? Select(
- GameInstallationsSettings settings,
- out IPhysicalPlayableObject? targetObject,
- out GameEngineType? actualEngineType)
- {
- var pathToVerify = settings.AutoPath;
- if (pathToVerify is null)
- throw new InvalidOperationException("path to verify cannot be null.");
-
- actualEngineType = settings.EngineType;
-
- GameFinderResult finderResult;
- try
- {
- finderResult = GameFinderService.FindGamesFromPathOrGlobal(pathToVerify);
- }
- catch (GameNotFoundException)
- {
- Logger?.LogError(ModVerifyConstants.ConsoleEventId, "Unable to find games based of the given location '{SettingsGamePath}'. Consider specifying all paths manually.", settings.GamePath);
- targetObject = null!;
- return null;
- }
-
-
- var modOrGame = GetAttachedModOrGame(finderResult, actualEngineType, pathToVerify);
-
- if (modOrGame is not null)
- {
- var actualType = modOrGame.Game.Type.ToEngineType();
- actualEngineType ??= actualType;
- if (actualEngineType != actualType)
- throw new ArgumentException($"The specified game type '{actualEngineType}' does not match the actual type of the game or mod to verify.");
-
- targetObject = modOrGame;
- return GetLocations(targetObject, finderResult, settings.AdditionalFallbackPaths);
- }
-
- if (!settings.EngineType.HasValue)
- throw new ArgumentException("Unable to determine game type. Use --type argument to set the game type.");
-
- Logger?.LogDebug("The requested mod at '{PathToVerify}' is detached from its games.", pathToVerify);
-
- // The path is a detached mod, that exists on a different location than the game.
- var result = GetDetachedModLocations(pathToVerify, finderResult, settings, out var mod);
- targetObject = mod;
- return result;
- }
-
- private IPhysicalPlayableObject? GetAttachedModOrGame(GameFinderResult finderResult, GameEngineType? requestedEngineType, string searchPath)
- {
- var fullSearchPath = _fileSystem.Path.GetFullPath(searchPath);
-
- if (finderResult.Game.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase))
- {
- if (finderResult.Game.Type.ToEngineType() != requestedEngineType)
- throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{searchPath}' to verify.");
- return finderResult.Game;
- }
-
- if (finderResult.FallbackGame is not null &&
- finderResult.FallbackGame.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase))
- {
- if (finderResult.FallbackGame.Type.ToEngineType() != requestedEngineType)
- throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{searchPath}' to verify.");
- return finderResult.FallbackGame;
- }
-
- return GetMatchingModFromGame(finderResult.Game, requestedEngineType, fullSearchPath) ??
- GetMatchingModFromGame(finderResult.FallbackGame, requestedEngineType, fullSearchPath);
- }
-
- private GameLocations GetDetachedModLocations(string modPath, GameFinderResult gameResult, GameInstallationsSettings settings, out IPhysicalMod mod)
- {
- IGame game = null!;
-
- if (gameResult.Game.Type.ToEngineType() == settings.EngineType)
- game = gameResult.Game;
- if (gameResult.FallbackGame is not null && gameResult.FallbackGame.Type.ToEngineType() == settings.EngineType)
- game = gameResult.FallbackGame;
-
- if (game is null)
- throw new GameNotFoundException($"Unable to find game of type '{settings.EngineType}'");
-
- var modFinder = ServiceProvider.GetRequiredService();
- var modRef = modFinder.FindMods(game, _fileSystem.DirectoryInfo.New(modPath)).FirstOrDefault();
-
- if (modRef is null)
- throw new NotSupportedException($"The mod at '{modPath}' is not compatible to the found game '{game}'.");
-
- var modFactory = ServiceProvider.GetRequiredService();
- mod = modFactory.CreatePhysicalMod(game, modRef, CultureInfo.InvariantCulture);
-
- game.AddMod(mod);
-
- mod.ResolveDependencies();
-
- return GetLocations(mod, gameResult, settings.AdditionalFallbackPaths);
- }
-
- private static IPhysicalMod? GetMatchingModFromGame(IGame? game, GameEngineType? requestedEngineType, string modPath)
- {
- if (game is null)
- return null;
-
- var isGameSupported = !requestedEngineType.HasValue || game.Type.ToEngineType() == requestedEngineType;
- foreach (var mod in game.Game.Mods)
- {
- if (mod is IPhysicalMod physicalMod)
- {
- if (physicalMod.Directory.FullName.Equals(modPath, StringComparison.OrdinalIgnoreCase))
- {
- if (!isGameSupported)
- throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the mod '{modPath}' to verify.");
- return physicalMod;
- }
- }
- }
-
- return null;
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/IModSelector.cs b/src/ModVerify.CliApp/ModSelectors/IModSelector.cs
deleted file mode 100644
index a04858c..0000000
--- a/src/ModVerify.CliApp/ModSelectors/IModSelector.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-using AET.ModVerify.App.Settings;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Infrastructure;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal interface IModSelector
-{
- GameLocations? Select(
- GameInstallationsSettings settings,
- out IPhysicalPlayableObject? targetObject,
- out GameEngineType? actualEngineType);
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs b/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs
deleted file mode 100644
index 34cf39d..0000000
--- a/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-using System;
-using AET.ModVerify.App.Settings;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Infrastructure;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal class ManualModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider)
-{
- public override GameLocations Select(
- GameInstallationsSettings settings,
- out IPhysicalPlayableObject? targetObject,
- out GameEngineType? actualEngineType)
- {
- actualEngineType = settings.EngineType;
- targetObject = null;
-
- if (!actualEngineType.HasValue)
- throw new ArgumentException("Unable to determine game type. Use --type argument to set the game type.");
-
- if (string.IsNullOrEmpty(settings.GamePath))
- throw new ArgumentException("Argument --game must be set.");
-
- return new GameLocations(
- settings.ModPaths,
- settings.GamePath!,
- GetFallbackPaths(settings.FallbackGamePath, settings.AdditionalFallbackPaths));
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs b/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs
deleted file mode 100644
index 8dd1d90..0000000
--- a/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs
+++ /dev/null
@@ -1,75 +0,0 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using AET.ModVerify.App.GameFinder;
-using AET.ModVerify.App.Settings;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Infrastructure;
-using PG.StarWarsGame.Infrastructure.Mods;
-using PG.StarWarsGame.Infrastructure.Services.Dependencies;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal abstract class ModSelectorBase : IModSelector
-{
- protected readonly ILogger? Logger;
- protected readonly GameFinderService GameFinderService;
- protected readonly IServiceProvider ServiceProvider;
-
- protected ModSelectorBase(IServiceProvider serviceProvider)
- {
- ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
- Logger = serviceProvider.GetService()?.CreateLogger(GetType());
- GameFinderService = new GameFinderService(serviceProvider);
- }
-
- public abstract GameLocations? Select(
- GameInstallationsSettings settings,
- out IPhysicalPlayableObject? targetObject,
- out GameEngineType? actualEngineType);
-
- protected GameLocations GetLocations(IPhysicalPlayableObject playableObject, GameFinderResult finderResult, IList additionalFallbackPaths)
- {
- var fallbacks = GetFallbackPaths(finderResult, playableObject, additionalFallbackPaths);
- var modPaths = GetModPaths(playableObject);
- return new GameLocations(modPaths, playableObject.Game.Directory.FullName, fallbacks);
- }
-
- private static IList GetFallbackPaths(GameFinderResult finderResult, IPlayableObject gameOrMod, IList additionalFallbackPaths)
- {
- var coercedFallbackGame = finderResult.FallbackGame;
- if (gameOrMod.Equals(finderResult.FallbackGame))
- coercedFallbackGame = null;
- else if (gameOrMod.Game.Equals(finderResult.FallbackGame))
- coercedFallbackGame = null;
-
- return GetFallbackPaths(coercedFallbackGame?.Directory.FullName, additionalFallbackPaths);
- }
-
-
- protected static IList GetFallbackPaths(string? fallbackGame, IList additionalFallbackPaths)
- {
- var fallbacks = new List();
- if (fallbackGame is not null)
- fallbacks.Add(fallbackGame);
- foreach (var fallback in additionalFallbackPaths)
- fallbacks.Add(fallback);
-
- return fallbacks;
- }
-
-
- private IList GetModPaths(IPhysicalPlayableObject modOrGame)
- {
- if (modOrGame is not IMod mod)
- return Array.Empty();
-
- var traverser = ServiceProvider.GetRequiredService();
- return traverser.Traverse(mod)
- .OfType().Select(x => x.Directory.FullName)
- .ToList();
- }
-
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs b/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs
deleted file mode 100644
index 07ef263..0000000
--- a/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs
+++ /dev/null
@@ -1,18 +0,0 @@
-using System;
-using AET.ModVerify.App.Settings;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal class ModSelectorFactory(IServiceProvider serviceProvider)
-{
- public IModSelector CreateSelector(GameInstallationsSettings settings)
- {
- if (settings.Interactive)
- return new ConsoleModSelector(serviceProvider);
- if (settings.UseAutoDetection)
- return new AutomaticModSelector(serviceProvider);
- if (settings.ManualSetup)
- return new ManualModSelector(serviceProvider);
- throw new ArgumentException("Unknown option configuration provided.");
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs
deleted file mode 100644
index 221bb9e..0000000
--- a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs
+++ /dev/null
@@ -1,40 +0,0 @@
-using System;
-using System.Linq;
-using AET.ModVerify.App.GameFinder;
-using AET.ModVerify.App.Settings;
-using PG.StarWarsGame.Engine;
-using PG.StarWarsGame.Infrastructure;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal class SettingsBasedModSelector(IServiceProvider serviceProvider)
-{
- public VerifyInstallationData CreateInstallationDataFromSettings(GameInstallationsSettings settings)
- {
- var gameLocations = new ModSelectorFactory(serviceProvider)
- .CreateSelector(settings)
- .Select(settings, out var targetObject, out var engineType);
-
- if (gameLocations is null)
- throw new GameNotFoundException("Unable to get game locations");
-
- if (engineType is null)
- throw new InvalidOperationException("Engine type not specified.");
-
- return new VerifyInstallationData
- {
- EngineType = engineType.Value,
- GameLocations = gameLocations,
- Name = GetNameFromGameLocations(targetObject, gameLocations, engineType.Value)
- };
- }
-
- private static string GetNameFromGameLocations(IPlayableObject? targetObject, GameLocations gameLocations, GameEngineType engineType)
- {
- if (targetObject is not null)
- return targetObject.Name;
-
- var mod = gameLocations.ModPaths.FirstOrDefault();
- return mod ?? gameLocations.GamePath;
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/VerifyInstallationData.cs b/src/ModVerify.CliApp/ModSelectors/VerifyInstallationData.cs
deleted file mode 100644
index 1a1fcd2..0000000
--- a/src/ModVerify.CliApp/ModSelectors/VerifyInstallationData.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Text;
-using PG.StarWarsGame.Engine;
-
-namespace AET.ModVerify.App.ModSelectors;
-
-internal sealed class VerifyInstallationData
-{
- public required string Name { get; init; }
-
- public required GameEngineType EngineType { get; init; }
-
- public required GameLocations GameLocations { get; init; }
-
- public override string ToString()
- {
- var sb = new StringBuilder();
-
- sb.AppendLine($"ObjectToVerify={Name};EngineType={EngineType};Locations=[");
- if (GameLocations.ModPaths.Count > 0)
- sb.AppendLine($"Mods=[{string.Join(";", GameLocations.ModPaths)}];");
- sb.AppendLine($"Game=[{GameLocations.GamePath}];");
- if (GameLocations.FallbackPaths.Count > 0)
- sb.AppendLine($"Fallbacks=[{string.Join(";", GameLocations.FallbackPaths)}];");
- sb.AppendLine("]");
-
- return sb.ToString();
- }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj
index 0073b2b..2301a28 100644
--- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj
+++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj
@@ -21,6 +21,10 @@
en
+
+ true
+
+
@@ -30,18 +34,18 @@
-
-
+
+
-
+
-
-
-
-
-
+
+
+
+
+
@@ -51,10 +55,6 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
all
@@ -64,9 +64,18 @@
-
- true
-
+
+
+
+ compile
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+ compile
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
diff --git a/src/ModVerify.CliApp/ModVerifyAppEnvironment.cs b/src/ModVerify.CliApp/ModVerifyAppEnvironment.cs
index 86bfc40..90a41db 100644
--- a/src/ModVerify.CliApp/ModVerifyAppEnvironment.cs
+++ b/src/ModVerify.CliApp/ModVerifyAppEnvironment.cs
@@ -1,4 +1,5 @@
-using System.IO.Abstractions;
+using System.IO;
+using System.IO.Abstractions;
using System.Reflection;
using AnakinRaW.ApplicationBase.Environment;
#if !NET
@@ -26,11 +27,17 @@ internal sealed class ModVerifyAppEnvironment(Assembly assembly, IFileSystem fil
public override ICollection UpdateMirrors { get; } = new List
{
#if DEBUG
- new("C:\\Test\\ModVerify"),
+ new(CreateDebugPath()),
#endif
new($"https://republicatwar.com/downloads/{ModVerifyConstants.ModVerifyToolPath}")
};
+ private static string CreateDebugPath()
+ {
+ var dir = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "../../../../.."));
+ return Path.Combine(dir, ".local_deploy/server");
+ }
+
public override string UpdateRegistryPath => $@"SOFTWARE\{ModVerifyConstants.ModVerifyToolPath}\Update";
protected override UpdateConfiguration CreateUpdateConfiguration()
diff --git a/src/ModVerify.CliApp/ModVerifyApplication.cs b/src/ModVerify.CliApp/ModVerifyApplication.cs
index 7ea461c..ee71dcf 100644
--- a/src/ModVerify.CliApp/ModVerifyApplication.cs
+++ b/src/ModVerify.CliApp/ModVerifyApplication.cs
@@ -1,5 +1,4 @@
-using AET.ModVerify.App.ModSelectors;
-using AET.ModVerify.App.Reporting;
+using AET.ModVerify.App.Reporting;
using AET.ModVerify.App.Settings;
using AET.ModVerify.Pipeline;
using AET.ModVerify.Reporting;
@@ -8,16 +7,14 @@
using AnakinRaW.ApplicationBase.Utilities;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using PG.StarWarsGame.Engine;
using Serilog;
using System;
using System.Collections.Generic;
-using System.IO;
using System.IO.Abstractions;
using System.Linq;
-using System.Threading;
using System.Threading.Tasks;
using AET.ModVerify.App.GameFinder;
+using AET.ModVerify.App.TargetSelectors;
using ILogger = Microsoft.Extensions.Logging.ILogger;
namespace AET.ModVerify.App;
@@ -28,21 +25,21 @@ internal sealed class ModVerifyApplication(ModVerifyAppSettings settings, IServi
private readonly IFileSystem _fileSystem = services.GetRequiredService();
private readonly ModVerifyAppEnvironment _appEnvironment = services.GetRequiredService();
- public async Task Run()
+ public async Task RunAsync()
{
using (new UnhandledExceptionHandler(services))
using (new UnobservedTaskExceptionHandler(services))
- return await RunCore().ConfigureAwait(false);
+ return await RunCoreAsync().ConfigureAwait(false);
}
- private async Task RunCore()
+ private async Task RunCoreAsync()
{
_logger?.LogDebug("Raw command line: {CommandLine}", Environment.CommandLine);
var interactive = settings.Interactive;
try
{
- return await RunVerify().ConfigureAwait(false);
+ return await RunModVerifyAsync().ConfigureAwait(false);
}
catch (Exception e)
{
@@ -68,13 +65,28 @@ private async Task RunCore()
}
- private async Task RunVerify()
+ private async Task RunModVerifyAsync()
{
- VerifyInstallationData installData;
+ VerificationTarget verificationTarget;
try
{
- installData = new SettingsBasedModSelector(services)
- .CreateInstallationDataFromSettings(settings.GameInstallationsSettings);
+ var targetSettings = settings.VerificationTargetSettings;
+ verificationTarget = new VerificationTargetSelectorFactory(services)
+ .CreateSelector(targetSettings)
+ .Select(targetSettings);
+ }
+ catch (ArgumentException ex)
+ {
+ ConsoleUtilities.WriteApplicationFatalError(_appEnvironment.ApplicationName,
+ $"The specified arguments are not correct: {ex.Message}");
+ _logger?.LogError(ex, "Invalid application arguments: {Message}", ex.Message);
+ return ex.HResult;
+ }
+ catch (TargetNotFoundException ex)
+ {
+ ConsoleUtilities.WriteApplicationFatalError(_appEnvironment.ApplicationName, ex.Message);
+ _logger?.LogError(ex, ex.Message);
+ return ex.HResult;
}
catch (GameNotFoundException ex)
{
@@ -84,84 +96,57 @@ private async Task RunVerify()
return ex.HResult;
}
- var reportSettings = CreateGlobalReportSettings(installData);
+ var reportSettings = CreateGlobalReportSettings(verificationTarget);
- _logger?.LogDebug("Verify install data: {InstallData}", installData);
+ _logger?.LogDebug("Verification taget: {Target}", verificationTarget);
_logger?.LogTrace("Verify settings: {Settings}", settings);
- var allErrors = await Verify(installData, reportSettings)
+ var allErrors = await VerifyTargetAsync(verificationTarget, reportSettings)
.ConfigureAwait(false);
+ // TODO: Refactor method to represent "verify" and "baseline" mode of the app.
+ // Also display to user more prominently which mode is active.
+
try
{
await ReportErrors(allErrors).ConfigureAwait(false);
}
catch (GameVerificationException e)
{
+ _logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
+ "The verification of {Target} completed with findings of the specified failure severity {Severity}",
+ verificationTarget.Name, settings.AppThrowsOnMinimumSeverity);
return e.HResult;
}
if (!settings.CreateNewBaseline)
return 0;
- await WriteBaseline(reportSettings, allErrors, settings.NewBaselinePath).ConfigureAwait(false);
+ await WriteBaselineAsync(verificationTarget, reportSettings, allErrors, settings.NewBaselinePath).ConfigureAwait(false);
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Baseline successfully created.");
return 0;
}
- private async Task> Verify(
- VerifyInstallationData installData,
+ private async Task> VerifyTargetAsync(
+ VerificationTarget verificationTarget,
GlobalVerifyReportSettings reportSettings)
{
- var gameEngineService = services.GetRequiredService();
- var engineErrorReporter = new ConcurrentGameEngineErrorReporter();
-
- IStarWarsGameEngine gameEngine;
-
- try
- {
- var initProgress = new Progress();
- var initProgressReporter = new EngineInitializeProgressReporter(initProgress);
-
- try
- {
- _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Creating Game Engine '{Engine}'", installData.EngineType);
- gameEngine = await gameEngineService.InitializeAsync(
- installData.EngineType,
- installData.GameLocations,
- engineErrorReporter,
- initProgress,
- false,
- CancellationToken.None).ConfigureAwait(false);
- _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Game Engine created");
- }
- finally
- {
- initProgressReporter.Dispose();
- }
- }
- catch (Exception e)
- {
- _logger?.LogError(e, "Creating game engine failed: {Message}", e.Message);
- throw;
- }
-
- var progressReporter = new VerifyConsoleProgressReporter(installData.Name);
+ var progressReporter = new VerifyConsoleProgressReporter(verificationTarget.Name);
using var verifyPipeline = new GameVerifyPipeline(
- gameEngine,
- engineErrorReporter,
+ verificationTarget,
settings.VerifyPipelineSettings,
reportSettings,
progressReporter,
+ new EngineInitializeProgressReporter(verificationTarget.Engine),
services);
try
{
try
{
- _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Verifying '{Target}'...", installData.Name);
+ _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Verifying '{Target}'...", verificationTarget.Name);
await verifyPipeline.RunAsync().ConfigureAwait(false);
progressReporter.Report(string.Empty, 1.0);
}
@@ -201,27 +186,21 @@ private async Task ReportErrors(IReadOnlyCollection errors)
throw new GameVerificationException(errors);
}
- private async Task WriteBaseline(
+ private async Task WriteBaselineAsync(
+ VerificationTarget target,
GlobalVerifyReportSettings reportSettings,
IEnumerable errors,
string baselineFile)
{
- var baseline = new VerificationBaseline(reportSettings.MinimumReportSeverity, errors);
-
- var fullPath = _fileSystem.Path.GetFullPath(baselineFile);
- _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Writing Baseline to '{FullPath}'", fullPath);
-
-#if NET
- await
-#endif
- using var fs = _fileSystem.FileStream.New(fullPath, FileMode.Create, FileAccess.Write, FileShare.None);
- await baseline.ToJsonAsync(fs);
+ var baselineFactory = services.GetRequiredService();
+ var baseline = baselineFactory.CreateBaseline(target, reportSettings, errors);
+ await baselineFactory.WriteBaselineAsync(baseline, baselineFile);
}
- private GlobalVerifyReportSettings CreateGlobalReportSettings(VerifyInstallationData installData)
+ private GlobalVerifyReportSettings CreateGlobalReportSettings(VerificationTarget verificationTarget)
{
var baselineSelector = new BaselineSelector(settings, services);
- var baseline = baselineSelector.SelectBaseline(installData, out var baselinePath);
+ var baseline = baselineSelector.SelectBaseline(verificationTarget, out var baselinePath);
if (baseline.Count > 0)
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Using baseline '{Baseline}'", baselinePath);
diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs
index cd4747b..2d293b9 100644
--- a/src/ModVerify.CliApp/Program.cs
+++ b/src/ModVerify.CliApp/Program.cs
@@ -173,7 +173,7 @@ protected override async Task RunAppAsync(string[] args, IServiceProvider a
return e.HResult;
}
- return await new ModVerifyApplication(modVerifySettings, appServiceProvider).Run().ConfigureAwait(false);
+ return await new ModVerifyApplication(modVerifySettings, appServiceProvider).RunAsync().ConfigureAwait(false);
}
private void SetupVerifyReporting(IServiceCollection serviceCollection)
diff --git a/src/ModVerify.CliApp/Properties/launchSettings.json b/src/ModVerify.CliApp/Properties/launchSettings.json
index e47583a..0dc1305 100644
--- a/src/ModVerify.CliApp/Properties/launchSettings.json
+++ b/src/ModVerify.CliApp/Properties/launchSettings.json
@@ -6,7 +6,7 @@
},
"Interactive Verify": {
"commandName": "Project",
- "commandLineArgs": "verify -o verifyResults --minFailSeverity Information --offline"
+ "commandLineArgs": "verify -o verifyResults --minFailSeverity Information --offline --failFast"
},
"Interactive Baseline": {
"commandName": "Project",
@@ -15,7 +15,7 @@
"FromModPath": {
"commandName": "Project",
- "commandLineArgs": "-o verifyResults --baseline focBaseline.json --path C:/test --type Foc"
+ "commandLineArgs": "verify -o verifyResults --path \"C:\\Program Files (x86)\\Steam\\steamapps\\common\\Star Wars Empire at War\\corruption\""
}
}
}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Reporting/BaselineFactory.cs b/src/ModVerify.CliApp/Reporting/BaselineFactory.cs
index 9fcc911..1b49e88 100644
--- a/src/ModVerify.CliApp/Reporting/BaselineFactory.cs
+++ b/src/ModVerify.CliApp/Reporting/BaselineFactory.cs
@@ -1,10 +1,13 @@
-using System;
+using AET.ModVerify.Reporting;
+using AET.ModVerify.Reporting.Settings;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using System;
+using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.IO.Abstractions;
-using AET.ModVerify.Reporting;
-using Microsoft.Extensions.DependencyInjection;
-using Microsoft.Extensions.Logging;
+using System.Threading.Tasks;
namespace AET.ModVerify.App.Reporting;
@@ -13,7 +16,7 @@ internal sealed class BaselineFactory(IServiceProvider serviceProvider)
private readonly ILogger? _logger = serviceProvider.GetService()?.CreateLogger(typeof(BaselineFactory));
private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService();
- public bool TryCreateBaseline(
+ public bool TryFindBaselineInDirectory(
string directory,
out VerificationBaseline baseline,
[NotNullWhen(true)] out string? path)
@@ -58,11 +61,31 @@ public bool TryCreateBaseline(
return false;
}
- public VerificationBaseline CreateBaseline(string filePath)
+ public VerificationBaseline ParseBaseline(string filePath)
{
return CreateBaselineFromFilePath(filePath);
}
+ public VerificationBaseline CreateBaseline(
+ VerificationTarget target,
+ GlobalVerifyReportSettings reportSettings,
+ IEnumerable errors)
+ {
+ return new VerificationBaseline(reportSettings.MinimumReportSeverity, errors, target);
+ }
+
+ public async Task WriteBaselineAsync(VerificationBaseline baseline, string filePath)
+ {
+ var fullPath = _fileSystem.Path.GetFullPath(filePath);
+ _logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Writing Baseline to '{FullPath}'", fullPath);
+
+#if NET
+ await
+#endif
+ using var fs = _fileSystem.FileStream.New(fullPath, FileMode.Create, FileAccess.Write, FileShare.None);
+ await baseline.ToJsonAsync(fs);
+ }
+
private VerificationBaseline CreateBaselineFromFilePath(string baselineFile)
{
using var fs = _fileSystem.FileStream.New(baselineFile, FileMode.Open, FileAccess.Read);
diff --git a/src/ModVerify.CliApp/Reporting/BaselineSelector.cs b/src/ModVerify.CliApp/Reporting/BaselineSelector.cs
index 95953f1..348c3a6 100644
--- a/src/ModVerify.CliApp/Reporting/BaselineSelector.cs
+++ b/src/ModVerify.CliApp/Reporting/BaselineSelector.cs
@@ -1,5 +1,4 @@
-using AET.ModVerify.App.ModSelectors;
-using AET.ModVerify.App.Resources.Baselines;
+using AET.ModVerify.App.Resources.Baselines;
using AET.ModVerify.App.Settings;
using AET.ModVerify.Reporting;
using AnakinRaW.ApplicationBase;
@@ -16,7 +15,7 @@ internal sealed class BaselineSelector(ModVerifyAppSettings settings, IServicePr
private readonly ILogger? _logger = services.GetService()?.CreateLogger(typeof(ModVerifyApplication));
private readonly BaselineFactory _baselineFactory = new(services);
- public VerificationBaseline SelectBaseline(VerifyInstallationData installationData, out string? usedBaselinePath)
+ public VerificationBaseline SelectBaseline(VerificationTarget verificationTarget, out string? usedBaselinePath)
{
var baselinePath = settings.ReportSettings.BaselinePath;
if (!string.IsNullOrEmpty(baselinePath))
@@ -24,7 +23,7 @@ public VerificationBaseline SelectBaseline(VerifyInstallationData installationDa
try
{
usedBaselinePath = baselinePath;
- return _baselineFactory.CreateBaseline(baselinePath!);
+ return _baselineFactory.ParseBaseline(baselinePath!);
}
catch (InvalidBaselineException e)
{
@@ -49,14 +48,14 @@ public VerificationBaseline SelectBaseline(VerifyInstallationData installationDa
}
if (settings.Interactive)
- return FindBaselineInteractive(installationData, out usedBaselinePath);
+ return FindBaselineInteractive(verificationTarget, out usedBaselinePath);
// If the application is not interactive, we only use a baseline file present in the directory of the verification target.
- return FindBaselineNonInteractive(installationData.GameLocations.TargetPath, out usedBaselinePath);
+ return FindBaselineNonInteractive(verificationTarget.Location.TargetPath, out usedBaselinePath);
}
- private VerificationBaseline FindBaselineInteractive(VerifyInstallationData installationData, out string? baselinePath)
+ private VerificationBaseline FindBaselineInteractive(VerificationTarget verificationTarget, out string? baselinePath)
{
// The application is in interactive mode. We apply the following lookup:
// 1. Use a baseline found in the directory of the verification target.
@@ -66,21 +65,21 @@ private VerificationBaseline FindBaselineInteractive(VerifyInstallationData inst
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Searching for local baseline files...");
- if (!_baselineFactory.TryCreateBaseline(installationData.GameLocations.TargetPath, out var baseline,
+ if (!_baselineFactory.TryFindBaselineInDirectory(verificationTarget.Location.TargetPath, out var baseline,
out baselinePath))
{
- if (!_baselineFactory.TryCreateBaseline("./", out baseline, out baselinePath))
+ if (!_baselineFactory.TryFindBaselineInDirectory("./", out baseline, out baselinePath))
{
// It does not make sense to load the game's default baselines if the user wants to verify the game,
// as the verification result would always be empty (at least in a non-development scenario)
- if (installationData.GameLocations.ModPaths.Count == 0)
+ if (verificationTarget.Location.ModPaths.Count == 0)
{
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "No local baseline file found.");
return VerificationBaseline.Empty;
}
Console.WriteLine("No baseline found locally.");
- return TryGetDefaultBaseline(installationData.EngineType, out baselinePath);
+ return TryGetDefaultBaseline(verificationTarget.Engine, out baselinePath);
}
}
@@ -116,7 +115,7 @@ private VerificationBaseline TryGetDefaultBaseline(GameEngineType engineType, ou
}
}
- internal VerificationBaseline LoadEmbeddedBaseline(GameEngineType engineType)
+ internal static VerificationBaseline LoadEmbeddedBaseline(GameEngineType engineType)
{
var baselineFileName = $"baseline-{engineType.ToString().ToLower()}.json";
var resourcePath = $"{typeof(BaselineResources).Namespace}.{baselineFileName}";
@@ -127,7 +126,7 @@ internal VerificationBaseline LoadEmbeddedBaseline(GameEngineType engineType)
private VerificationBaseline FindBaselineNonInteractive(string targetPath, out string? usedPath)
{
- if (_baselineFactory.TryCreateBaseline(targetPath, out var baseline, out usedPath))
+ if (_baselineFactory.TryFindBaselineInDirectory(targetPath, out var baseline, out usedPath))
{
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId, "Automatically applying local baseline file '{Path}'.", usedPath);
return baseline;
diff --git a/src/ModVerify.CliApp/Reporting/EngineInitializeProgressReporter.cs b/src/ModVerify.CliApp/Reporting/EngineInitializeProgressReporter.cs
index b994e97..d93462f 100644
--- a/src/ModVerify.CliApp/Reporting/EngineInitializeProgressReporter.cs
+++ b/src/ModVerify.CliApp/Reporting/EngineInitializeProgressReporter.cs
@@ -1,30 +1,25 @@
using System;
+using PG.StarWarsGame.Engine;
namespace AET.ModVerify.App.Reporting;
-internal sealed class EngineInitializeProgressReporter : IDisposable
-{
- private Progress? _progress;
-
- public EngineInitializeProgressReporter(Progress? progress)
+internal sealed class EngineInitializeProgressReporter(GameEngineType engine) : IGameEngineInitializationReporter
+{
+ public void ReportProgress(string message)
{
- if (progress is null)
- return;
- progress.ProgressChanged += OnProgress;
+ Console.ForegroundColor = ConsoleColor.DarkGray;
+ Console.WriteLine(message);
+ Console.ResetColor();
}
- private void OnProgress(object sender, string e)
+ public void ReportStarted()
{
- Console.ForegroundColor = ConsoleColor.DarkGray;
- Console.WriteLine(e);
- Console.ResetColor();
+ Console.WriteLine($"Initializing game engine '{engine}'...");
}
- public void Dispose()
+ public void ReportFinished()
{
+ Console.WriteLine($"Game engine initialized.");
Console.WriteLine();
- if (_progress is not null)
- _progress.ProgressChanged -= OnProgress;
- _progress = null;
}
}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json b/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
index c94d121..2cb5cac 100644
--- a/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
+++ b/src/ModVerify.CliApp/Resources/Baselines/baseline-foc.json
@@ -1,5 +1,16 @@
{
- "version": "2.0",
+ "version": "2.1",
+ "target": {
+ "name": "Forces of Corruption (SteamGold)",
+ "engine": "Foc",
+ "location": {
+ "modPaths": [],
+ "gamePath": "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Star Wars Empire at War\\corruption",
+ "fallbackPaths": [
+ "C:\\Program Files (x86)\\Steam\\steamapps\\common\\Star Wars Empire at War\\GameData"
+ ]
+ }
+ },
"minSeverity": "Information",
"errors": [
{
@@ -36,12 +47,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_SKIPRAY.ALO\u0027.",
+ "message": "Unable to find .ALO file \u0027CIN_Reb_CelebHall.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\UV_SKIPRAY.ALO"
- ],
- "asset": "Default.fx"
+ "context": [],
+ "asset": "CIN_Reb_CelebHall.alo"
},
{
"id": "FILE00",
@@ -49,36 +58,26 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
+ "message": "Proxy particle \u0027p_ssd_debris\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
- ],
- "asset": "p_smoke_small_thin2"
- },
- {
- "id": "FILE00",
- "verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO"
],
- "message": "Unable to find .ALO file \u0027W_Kamino_Reflect.ALO\u0027",
- "severity": "Error",
- "context": [],
- "asset": "W_Kamino_Reflect.ALO"
+ "asset": "p_ssd_debris"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Proxy particle \u0027p_ssd_debris\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO\u0027",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE_UC_DC.ALO"
+ "W_SITH_LEFTHALL.ALO"
],
- "asset": "p_ssd_debris"
+ "asset": "Cin_Reb_CelebHall_Wall.tga"
},
{
"id": "FILE00",
@@ -86,10 +85,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_p_proton_torpedo.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_ImperialCraft.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_p_proton_torpedo.alo"
+ "asset": "Cin_ImperialCraft.alo"
},
{
"id": "FILE00",
@@ -97,10 +96,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DStar_LeverPanel.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_Officer.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DStar_LeverPanel.alo"
+ "asset": "Cin_Officer.alo"
},
{
"id": "FILE00",
@@ -108,12 +107,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_protons.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE.ALO"
- ],
- "asset": "lookat"
+ "context": [],
+ "asset": "Cin_DStar_protons.alo"
},
{
"id": "FILE00",
@@ -122,12 +119,12 @@
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
"AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Could not find texture \u0027Cin_DeathStar.tga\u0027 for context: [ALTTEST.ALO].",
+ "message": "Could not find texture \u0027w_grenade.tga\u0027 for context: [W_GRENADE.ALO].",
"severity": "Error",
"context": [
- "ALTTEST.ALO"
+ "W_GRENADE.ALO"
],
- "asset": "Cin_DeathStar.tga"
+ "asset": "w_grenade.tga"
},
{
"id": "FILE00",
@@ -135,12 +132,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_prison_light\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_03_STATION_D.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ "DATA\\ART\\MODELS\\UB_03_STATION_D.ALO"
],
- "asset": "p_prison_light"
+ "asset": "p_uwstation_death"
},
{
"id": "FILE00",
@@ -148,26 +145,21 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO\u0027.",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Vader.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO"
- ],
- "asset": "Default.fx"
+ "context": [],
+ "asset": "Cin_EI_Vader.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027w_grenade.tga\u0027 for context: [W_GRENADE.ALO].",
+ "message": "Unable to find .ALO file \u0027MODELS\u0027",
"severity": "Error",
- "context": [
- "W_GRENADE.ALO"
- ],
- "asset": "w_grenade.tga"
+ "context": [],
+ "asset": "MODELS"
},
{
"id": "FILE00",
@@ -175,10 +167,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_NavyRow.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_Wall.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Rbel_NavyRow.alo"
+ "asset": "Cin_DeathStar_Wall.alo"
},
{
"id": "FILE00",
@@ -186,10 +178,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_Planet_Alderaan_High.alo\u0027",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Planet_Alderaan_High.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ],
+ "asset": "p_smoke_small_thin2"
},
{
"id": "FILE00",
@@ -197,12 +191,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO\u0027",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_01_STATION_D.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO"
+ "DATA\\ART\\MODELS\\UB_01_STATION_D.ALO"
],
- "asset": "lookat"
+ "asset": "p_uwstation_death"
},
{
"id": "FILE00",
@@ -210,12 +204,23 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\EI_MARAJADE.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Officer_Row.alo\u0027",
+ "severity": "Error",
+ "context": [],
+ "asset": "CIN_Officer_Row.alo"
+ },
+ {
+ "id": "FILE00",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ ],
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\EI_MARAJADE.ALO"
+ "DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO"
],
- "asset": "p_desert_ground_dust"
+ "asset": "Lensflare0"
},
{
"id": "FILE00",
@@ -223,10 +228,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027p_splash_wake_lava.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_DeathStar_Hangar.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "p_splash_wake_lava.alo"
+ "asset": "CIN_DeathStar_Hangar.alo"
},
{
"id": "FILE00",
@@ -234,10 +239,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_rv_XWingProp.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_EV_lambdaShuttle_150.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_rv_XWingProp.alo"
+ "asset": "Cin_EV_lambdaShuttle_150.alo"
},
{
"id": "FILE00",
@@ -245,10 +250,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Fire_Huge.alo\u0027",
+ "message": "Proxy particle \u0027p_smoke_small_thin4\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Fire_Huge.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ],
+ "asset": "p_smoke_small_thin4"
},
{
"id": "FILE00",
@@ -256,10 +263,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Probe_Droid.alo\u0027",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_Probe_Droid.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\W_STARS_CINE.ALO"
+ ],
+ "asset": "Lensflare0"
},
{
"id": "FILE00",
@@ -267,12 +276,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_05_STATION_D.ALO\u0027",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_SKIPRAY.ALO\u0027.",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UB_05_STATION_D.ALO"
+ "DATA\\ART\\MODELS\\UV_SKIPRAY.ALO"
],
- "asset": "p_uwstation_death"
+ "asset": "Default.fx"
},
{
"id": "FILE00",
@@ -280,10 +289,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO\u0027",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_IG88.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO"
+ "DATA\\ART\\MODELS\\UI_IG88.ALO"
],
"asset": "p_desert_ground_dust"
},
@@ -293,26 +302,34 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_steam_small\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_p_proton_torpedo.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO"
+ "context": [],
+ "asset": "CIN_p_proton_torpedo.alo"
+ },
+ {
+ "id": "FILE00",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "asset": "p_steam_small"
+ "message": "Unable to find .ALO file \u0027CIN_Fire_Huge.alo\u0027",
+ "severity": "Error",
+ "context": [],
+ "asset": "CIN_Fire_Huge.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027p_particle_master\u0027 for context: [P_DIRT_EMITTER_TEST1.ALO].",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_04_STATION_D.ALO\u0027",
"severity": "Error",
"context": [
- "P_DIRT_EMITTER_TEST1.ALO"
+ "DATA\\ART\\MODELS\\UB_04_STATION_D.ALO"
],
- "asset": "p_particle_master"
+ "asset": "p_uwstation_death"
},
{
"id": "FILE00",
@@ -320,12 +337,23 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_smoke_small_thin4\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027RV_nebulonb_D_death_00.ALO\u0027",
+ "severity": "Error",
+ "context": [],
+ "asset": "RV_nebulonb_D_death_00.ALO"
+ },
+ {
+ "id": "FILE00",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ ],
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_02_STATION_D.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ "DATA\\ART\\MODELS\\UB_02_STATION_D.ALO"
],
- "asset": "p_smoke_small_thin4"
+ "asset": "p_uwstation_death"
},
{
"id": "FILE00",
@@ -333,10 +361,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_EI_Vader.alo\u0027",
+ "message": "Unable to find .ALO file \u0027W_Kamino_Reflect.ALO\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_EI_Vader.alo"
+ "asset": "W_Kamino_Reflect.ALO"
},
{
"id": "FILE00",
@@ -344,10 +372,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO\u0027",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO"
+ "DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO"
],
"asset": "p_smoke_small_thin2"
},
@@ -357,12 +385,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO\u0027.",
+ "message": "Proxy particle \u0027p_steam_small\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO"
+ "DATA\\ART\\MODELS\\RB_HEAVYVEHICLEFACTORY.ALO"
],
- "asset": "Default.fx"
+ "asset": "p_steam_small"
},
{
"id": "FILE00",
@@ -370,10 +398,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DeathStar_Wall.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_EV_Stardestroyer_Warp.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DeathStar_Wall.alo"
+ "asset": "Cin_EV_Stardestroyer_Warp.alo"
},
{
"id": "FILE00",
@@ -381,10 +409,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027W_droid_steam.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_TurretLasers.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "W_droid_steam.alo"
+ "asset": "Cin_DStar_TurretLasers.alo"
},
{
"id": "FILE00",
@@ -392,10 +420,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_GreyGroup.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DeathStar_High.alo"
+ "asset": "CIN_Rbel_GreyGroup.alo"
},
{
"id": "FILE00",
@@ -403,10 +431,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027MODELS\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_Planet_Hoth_High.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "MODELS"
+ "asset": "Cin_Planet_Hoth_High.alo"
},
{
"id": "FILE00",
@@ -414,10 +442,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027W_AllShaders.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Trooper_Row.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "W_AllShaders.ALO"
+ "asset": "CIN_Trooper_Row.alo"
},
{
"id": "FILE00",
@@ -425,12 +453,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_bomb_spin\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO\u0027",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_SABOTEUR.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO"
+ "DATA\\ART\\MODELS\\UI_SABOTEUR.ALO"
],
- "asset": "p_bomb_spin"
+ "asset": "p_desert_ground_dust"
},
{
"id": "FILE00",
@@ -438,12 +466,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_03_STATION_D.ALO\u0027",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UB_03_STATION_D.ALO"
+ "DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO"
],
- "asset": "p_uwstation_death"
+ "asset": "Lensflare0"
},
{
"id": "FILE00",
@@ -451,10 +479,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_GreyGroup.alo\u0027",
+ "message": "Unable to find .ALO file \u0027W_AllShaders.ALO\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Rbel_GreyGroup.alo"
+ "asset": "W_AllShaders.ALO"
},
{
"id": "FILE00",
@@ -462,12 +490,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_cold_tiny01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_SCH.ALO\u0027",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO\u0027.",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_SCH.ALO"
+ "DATA\\ART\\MODELS\\EV_TIE_LANCET.ALO"
],
- "asset": "p_cold_tiny01"
+ "asset": "Default.fx"
},
{
"id": "FILE00",
@@ -486,34 +514,38 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_hp_archammer-damage\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_EI_Palpatine.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO"
- ],
- "asset": "p_hp_archammer-damage"
+ "context": [],
+ "asset": "Cin_EI_Palpatine.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_grey.alo\u0027",
+ "message": "Could not find texture \u0027Cin_DeathStar.tga\u0027 for context: [ALTTEST.ALO].",
"severity": "Error",
- "context": [],
- "asset": "CIN_Rbel_grey.alo"
+ "context": [
+ "ALTTEST.ALO"
+ ],
+ "asset": "Cin_DeathStar.tga"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Reb_CelebHall.alo\u0027",
+ "message": "Could not find texture \u0027UB_girder_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
"severity": "Error",
- "context": [],
- "asset": "CIN_Reb_CelebHall.alo"
+ "context": [
+ "UV_MDU_CAGE.ALO"
+ ],
+ "asset": "UB_girder_B.tga"
},
{
"id": "FILE00",
@@ -534,10 +566,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_ImperialCraft.alo\u0027",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO\u0027.",
"severity": "Error",
- "context": [],
- "asset": "Cin_ImperialCraft.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\EV_MDU_SENSORNODE.ALO"
+ ],
+ "asset": "Default.fx"
},
{
"id": "FILE00",
@@ -545,10 +579,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DStar_Dish_close.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_Planet_Alderaan_High.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DStar_Dish_close.alo"
+ "asset": "Cin_Planet_Alderaan_High.alo"
},
{
"id": "FILE00",
@@ -556,12 +590,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027pe_bwing_yellow\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_BWING.ALO\u0027",
+ "message": "Proxy particle \u0027p_hp_archammer-damage\u0027 not found for model \u0027DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\RV_BWING.ALO"
+ "DATA\\ART\\MODELS\\EV_ARCHAMMER.ALO"
],
- "asset": "pe_bwing_yellow"
+ "asset": "p_hp_archammer-damage"
},
{
"id": "FILE00",
@@ -569,10 +603,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_bridge.alo\u0027",
+ "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_05_STATION_D.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_bridge.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\UB_05_STATION_D.ALO"
+ ],
+ "asset": "p_uwstation_death"
},
{
"id": "FILE00",
@@ -580,12 +616,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_SABOTEUR.ALO\u0027",
+ "message": "Proxy particle \u0027p_explosion_smoke_small_thin5\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UI_SABOTEUR.ALO"
+ "DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO"
],
- "asset": "p_desert_ground_dust"
+ "asset": "p_explosion_smoke_small_thin5"
},
{
"id": "FILE00",
@@ -593,10 +629,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Trooper_Row.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Probe_Droid.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Trooper_Row.alo"
+ "asset": "CIN_Probe_Droid.alo"
},
{
"id": "FILE00",
@@ -604,10 +640,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_EV_TieAdvanced.alo\u0027",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_HIGH.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_EV_TieAdvanced.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\W_STARS_HIGH.ALO"
+ ],
+ "asset": "Lensflare0"
},
{
"id": "FILE00",
@@ -615,38 +653,58 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027w_sith_arch.alo\u0027",
+ "message": "Unable to find .ALO file \u0027W_Volcano_Rock02.ALO\u0027",
"severity": "Error",
"context": [],
- "asset": "w_sith_arch.alo"
+ "asset": "W_Volcano_Rock02.ALO"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027NB_YsalamiriTree_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
+ "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE.ALO\u0027",
"severity": "Error",
"context": [
- "UV_MDU_CAGE.ALO"
+ "DATA\\ART\\MODELS\\UV_ECLIPSE.ALO"
],
- "asset": "NB_YsalamiriTree_B.tga"
+ "asset": "lookat"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [EV_TIE_PHANTOM.ALO].",
+ "message": "Unable to find .ALO file \u0027Cin_Shuttle_Tyderium.alo\u0027",
+ "severity": "Error",
+ "context": [],
+ "asset": "Cin_Shuttle_Tyderium.alo"
+ },
+ {
+ "id": "FILE00",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ ],
+ "message": "Unable to find .ALO file \u0027W_SwampGasEmit.ALO\u0027",
+ "severity": "Error",
+ "context": [],
+ "asset": "W_SwampGasEmit.ALO"
+ },
+ {
+ "id": "FILE00",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ ],
+ "message": "Proxy particle \u0027P_heat_small01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_VCH.ALO\u0027",
"severity": "Error",
"context": [
- "EV_TIE_PHANTOM.ALO"
+ "DATA\\ART\\MODELS\\NB_VCH.ALO"
],
- "asset": "W_TE_Rock_f_02_b.tga"
+ "asset": "P_heat_small01"
},
{
"id": "FILE00",
@@ -654,10 +712,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_EI_Palpatine.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_NavyRow.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_EI_Palpatine.alo"
+ "asset": "CIN_Rbel_NavyRow.alo"
},
{
"id": "FILE00",
@@ -665,10 +723,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Fire_Medium.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Rbel_Soldier.alo"
+ "asset": "CIN_Fire_Medium.alo"
},
{
"id": "FILE00",
@@ -676,12 +734,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO\u0027",
+ "message": "Proxy particle \u0027p_ewok_drag_dirt\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_MONCAL_BUILDING.ALO"
+ "DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO"
],
- "asset": "p_smoke_small_thin2"
+ "asset": "p_ewok_drag_dirt"
},
{
"id": "FILE00",
@@ -700,10 +758,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Officer_Row.alo\u0027",
+ "message": "Unable to find .ALO file \u0027W_droid_steam.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Officer_Row.alo"
+ "asset": "W_droid_steam.alo"
},
{
"id": "FILE00",
@@ -711,26 +769,21 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_HIGH.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Biker_Row.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\W_STARS_HIGH.ALO"
- ],
- "asset": "Lensflare0"
+ "context": [],
+ "asset": "CIN_Biker_Row.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
+ "message": "Unable to find .ALO file \u0027w_planet_volcanic.alo\u0027",
"severity": "Error",
- "context": [
- "W_SITH_LEFTHALL.ALO"
- ],
- "asset": "Cin_Reb_CelebHall_Wall_B.tga"
+ "context": [],
+ "asset": "w_planet_volcanic.alo"
},
{
"id": "FILE00",
@@ -738,10 +791,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_Coruscant.alo\u0027",
+ "message": "Proxy particle \u0027p_smoke_small_thin2\u0027 not found for model \u0027DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Coruscant.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\RB_HYPERVELOCITYGUN.ALO"
+ ],
+ "asset": "p_smoke_small_thin2"
},
{
"id": "FILE00",
@@ -749,12 +804,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_ewok_drag_dirt\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO\u0027",
+ "message": "Proxy particle \u0027lookat\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UI_EWOK_HANDLER.ALO"
+ "DATA\\ART\\MODELS\\UV_ECLIPSE_UC.ALO"
],
- "asset": "p_ewok_drag_dirt"
+ "asset": "lookat"
},
{
"id": "FILE00",
@@ -762,12 +817,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027P_heat_small01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_VCH.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_REb_CelebCharacters.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\NB_VCH.ALO"
- ],
- "asset": "P_heat_small01"
+ "context": [],
+ "asset": "CIN_REb_CelebCharacters.alo"
},
{
"id": "FILE00",
@@ -775,36 +828,38 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027W_Vol_Steam01.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DeathStar_High.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "W_Vol_Steam01.ALO"
+ "asset": "Cin_DeathStar_High.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Proxy particle \u0027p_explosion_smoke_small_thin5\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO\u0027",
+ "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall_B.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\NB_NOGHRI_HUT.ALO"
+ "W_SITH_LEFTHALL.ALO"
],
- "asset": "p_explosion_smoke_small_thin5"
+ "asset": "Cin_Reb_CelebHall_Wall_B.tga"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO\u0027",
+ "message": "Could not find texture \u0027NB_YsalamiriTree_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_MEDIUM.ALO"
+ "UV_MDU_CAGE.ALO"
],
- "asset": "Lensflare0"
+ "asset": "NB_YsalamiriTree_B.tga"
},
{
"id": "FILE00",
@@ -812,12 +867,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_02_STATION_D.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_Coruscant.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\UB_02_STATION_D.ALO"
- ],
- "asset": "p_uwstation_death"
+ "context": [],
+ "asset": "Cin_Coruscant.alo"
},
{
"id": "FILE00",
@@ -825,10 +878,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_Officer.alo\u0027",
+ "message": "Proxy particle \u0027p_prison_light\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_PRISON.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "Cin_Officer.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\NB_PRISON.ALO"
+ ],
+ "asset": "p_prison_light"
},
{
"id": "FILE00",
@@ -836,12 +891,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_04_STATION_D.ALO\u0027",
+ "message": "Proxy particle \u0027p_cold_tiny01\u0027 not found for model \u0027DATA\\ART\\MODELS\\NB_SCH.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UB_04_STATION_D.ALO"
+ "DATA\\ART\\MODELS\\NB_SCH.ALO"
],
- "asset": "p_uwstation_death"
+ "asset": "p_cold_tiny01"
},
{
"id": "FILE00",
@@ -849,10 +904,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Lambda_Head.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_NavyTrooper_Row.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Lambda_Head.alo"
+ "asset": "CIN_NavyTrooper_Row.alo"
},
{
"id": "FILE00",
@@ -860,10 +915,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Biker_Row.alo\u0027",
+ "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO\u0027.",
"severity": "Error",
- "context": [],
- "asset": "CIN_Biker_Row.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO"
+ ],
+ "asset": "Default.fx"
},
{
"id": "FILE00",
@@ -871,10 +928,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DStar_protons.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DStar_protons.alo"
+ "asset": "CIN_Rbel_Soldier.alo"
},
{
"id": "FILE00",
@@ -882,10 +939,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\UI_IG88.ALO\u0027",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UI_IG88.ALO"
+ "DATA\\ART\\MODELS\\RI_KYLEKATARN.ALO"
],
"asset": "p_desert_ground_dust"
},
@@ -904,12 +961,15 @@
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Unable to find .ALO file \u0027Cin_Planet_Hoth_High.alo\u0027",
+ "message": "Could not find texture \u0027p_particle_master\u0027 for context: [P_DIRT_EMITTER_TEST1.ALO].",
"severity": "Error",
- "context": [],
- "asset": "Cin_Planet_Hoth_High.alo"
+ "context": [
+ "P_DIRT_EMITTER_TEST1.ALO"
+ ],
+ "asset": "p_particle_master"
},
{
"id": "FILE00",
@@ -917,12 +977,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_LOW.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_bridge.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\W_STARS_LOW.ALO"
- ],
- "asset": "Lensflare0"
+ "context": [],
+ "asset": "Cin_bridge.alo"
},
{
"id": "FILE00",
@@ -930,10 +988,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_NavyTrooper_Row.alo\u0027",
+ "message": "Unable to find .ALO file \u0027W_Vol_Steam01.ALO\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_NavyTrooper_Row.alo"
+ "asset": "W_Vol_Steam01.ALO"
},
{
"id": "FILE00",
@@ -941,10 +999,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_DStar_TurretLasers.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_grey.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_DStar_TurretLasers.alo"
+ "asset": "CIN_Rbel_grey.alo"
},
{
"id": "FILE00",
@@ -952,10 +1010,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027W_SwampGasEmit.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027w_sith_arch.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "W_SwampGasEmit.ALO"
+ "asset": "w_sith_arch.alo"
},
{
"id": "FILE00",
@@ -963,10 +1021,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_Shuttle_Tyderium.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_rv_XWingProp.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_Shuttle_Tyderium.alo"
+ "asset": "Cin_rv_XWingProp.alo"
},
{
"id": "FILE00",
@@ -974,23 +1032,24 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_EV_Stardestroyer_Warp.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_Dish_close.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "Cin_EV_Stardestroyer_Warp.alo"
+ "asset": "Cin_DStar_Dish_close.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
+ "AET.ModVerify.Verifiers.Commons.TextureVeifier"
],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO\u0027",
+ "message": "Could not find texture \u0027W_TE_Rock_f_02_b.tga\u0027 for context: [EV_TIE_PHANTOM.ALO].",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_CINE_LUA.ALO"
+ "EV_TIE_PHANTOM.ALO"
],
- "asset": "Lensflare0"
+ "asset": "W_TE_Rock_f_02_b.tga"
},
{
"id": "FILE00",
@@ -998,10 +1057,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_DeathStar_Hangar.alo\u0027",
+ "message": "Proxy particle \u0027pe_bwing_yellow\u0027 not found for model \u0027DATA\\ART\\MODELS\\RV_BWING.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_DeathStar_Hangar.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\RV_BWING.ALO"
+ ],
+ "asset": "pe_bwing_yellow"
},
{
"id": "FILE00",
@@ -1009,10 +1070,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Fire_Medium.alo\u0027",
+ "message": "Unable to find .ALO file \u0027CIN_Lambda_Head.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Fire_Medium.alo"
+ "asset": "CIN_Lambda_Head.alo"
},
{
"id": "FILE00",
@@ -1020,12 +1081,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_CINE.ALO\u0027",
+ "message": "Proxy particle \u0027p_explosion_small_delay00\u0027 not found for model \u0027DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO\u0027",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\W_STARS_CINE.ALO"
+ "DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO"
],
- "asset": "Lensflare0"
+ "asset": "p_explosion_small_delay00"
},
{
"id": "FILE00",
@@ -1033,10 +1094,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier_Group.alo\u0027",
+ "message": "Unable to find .ALO file \u0027Cin_DStar_LeverPanel.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "CIN_Rbel_Soldier_Group.alo"
+ "asset": "Cin_DStar_LeverPanel.alo"
},
{
"id": "FILE00",
@@ -1044,10 +1105,10 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027RV_nebulonb_D_death_00.ALO\u0027",
+ "message": "Unable to find .ALO file \u0027p_splash_wake_lava.alo\u0027",
"severity": "Error",
"context": [],
- "asset": "RV_nebulonb_D_death_00.ALO"
+ "asset": "p_splash_wake_lava.alo"
},
{
"id": "FILE00",
@@ -1055,10 +1116,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027W_Volcano_Rock02.ALO\u0027",
+ "message": "Proxy particle \u0027Lensflare0\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_STARS_LOW.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "W_Volcano_Rock02.ALO"
+ "context": [
+ "DATA\\ART\\MODELS\\W_STARS_LOW.ALO"
+ ],
+ "asset": "Lensflare0"
},
{
"id": "FILE00",
@@ -1066,10 +1129,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027w_planet_volcanic.alo\u0027",
+ "message": "Proxy particle \u0027p_desert_ground_dust\u0027 not found for model \u0027DATA\\ART\\MODELS\\EI_MARAJADE.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "w_planet_volcanic.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\EI_MARAJADE.ALO"
+ ],
+ "asset": "p_desert_ground_dust"
},
{
"id": "FILE00",
@@ -1077,10 +1142,12 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Unable to find .ALO file \u0027CIN_REb_CelebCharacters.alo\u0027",
+ "message": "Proxy particle \u0027p_bomb_spin\u0027 not found for model \u0027DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO\u0027",
"severity": "Error",
- "context": [],
- "asset": "CIN_REb_CelebCharacters.alo"
+ "context": [
+ "DATA\\ART\\MODELS\\W_THERMAL_DETONATOR_EMPIRE.ALO"
+ ],
+ "asset": "p_bomb_spin"
},
{
"id": "FILE00",
@@ -1088,257 +1155,249 @@
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
"AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Shader effect \u0027Default.fx\u0027 not found for model \u0027DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO\u0027.",
+ "message": "Unable to find .ALO file \u0027Cin_EV_TieAdvanced.alo\u0027",
"severity": "Error",
- "context": [
- "DATA\\ART\\MODELS\\UV_CRUSADERCLASSCORVETTE.ALO"
- ],
- "asset": "Default.fx"
+ "context": [],
+ "asset": "Cin_EV_TieAdvanced.alo"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
],
- "message": "Could not find texture \u0027Cin_Reb_CelebHall_Wall.tga\u0027 for context: [W_SITH_LEFTHALL.ALO].",
+ "message": "Unable to find .ALO file \u0027CIN_Rbel_Soldier_Group.alo\u0027",
"severity": "Error",
- "context": [
- "W_SITH_LEFTHALL.ALO"
- ],
- "asset": "Cin_Reb_CelebHall_Wall.tga"
+ "context": [],
+ "asset": "CIN_Rbel_Soldier_Group.alo"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Unable to find .ALO file \u0027Cin_EV_lambdaShuttle_150.alo\u0027",
+ "message": "Audio file \u0027U000_LEI0213_ENG.WAV\u0027 could not be found.",
"severity": "Error",
- "context": [],
- "asset": "Cin_EV_lambdaShuttle_150.alo"
+ "context": [
+ "Unit_Move_Leia"
+ ],
+ "asset": "U000_LEI0213_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Proxy particle \u0027p_explosion_small_delay00\u0027 not found for model \u0027DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO\u0027",
+ "message": "Audio file \u0027U000_LEI0113_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\EB_COMMANDCENTER.ALO"
+ "Unit_Select_Leia"
],
- "asset": "p_explosion_small_delay00"
+ "asset": "U000_LEI0113_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier",
- "AET.ModVerify.Verifiers.Commons.TextureVeifier"
+ "AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Could not find texture \u0027UB_girder_B.tga\u0027 for context: [UV_MDU_CAGE.ALO].",
+ "message": "Audio file \u0027U000_LEI0603_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "UV_MDU_CAGE.ALO"
+ "Unit_Increase_Production_Leia"
],
- "asset": "UB_girder_B.tga"
+ "asset": "U000_LEI0603_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.ReferencedModelsVerifier",
- "AET.ModVerify.Verifiers.Commons.SingleModelVerifier"
+ "AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Proxy particle \u0027p_uwstation_death\u0027 not found for model \u0027DATA\\ART\\MODELS\\UB_01_STATION_D.ALO\u0027",
+ "message": "Audio file \u0027U000_LEI0309_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "DATA\\ART\\MODELS\\UB_01_STATION_D.ALO"
+ "Unit_Attack_Leia"
],
- "asset": "p_uwstation_death"
+ "asset": "U000_LEI0309_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0212_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Move_Leia"
],
- "asset": "U000_LEI0206_ENG.WAV"
+ "asset": "U000_LEI0212_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0204_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_MAL0503_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Assist_Move_Missile_Launcher"
],
- "asset": "U000_LEI0204_ENG.WAV"
+ "asset": "U000_MAL0503_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0102_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_MCF1601_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_StarDest_MC30_Frigate"
],
- "asset": "U000_LEI0102_ENG.WAV"
+ "asset": "U000_MCF1601_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0215_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0111_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0215_ENG.WAV"
+ "asset": "U000_LEI0111_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0107_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_ARC3106_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Complete_Troops_Arc_Hammer"
],
- "asset": "U000_LEI0107_ENG.WAV"
+ "asset": "U000_ARC3106_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0504_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0303_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Remove_Corruption_Leia"
+ "Unit_Attack_Leia"
],
- "asset": "U000_LEI0504_ENG.WAV"
+ "asset": "U000_LEI0303_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027AMB_DES_CLEAR_LOOP_1.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0404_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Weather_Ambient_Clear_Sandstorm_Loop"
+ "Unit_Guard_Leia"
],
- "asset": "AMB_DES_CLEAR_LOOP_1.WAV"
+ "asset": "U000_LEI0404_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0105_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027TESTUNITMOVE_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Move_Gneneric_Test"
],
- "asset": "U000_LEI0105_ENG.WAV"
+ "asset": "TESTUNITMOVE_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0213_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0401_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Guard_Leia"
],
- "asset": "U000_LEI0213_ENG.WAV"
+ "asset": "U000_LEI0401_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027EGL_STAR_VIPER_SPINNING_1.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Star_Viper_Spinning_By"
],
- "asset": "U000_LEI0201_ENG.WAV"
+ "asset": "EGL_STAR_VIPER_SPINNING_1.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0303_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_TMC0212_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Move_Tie_Mauler"
],
- "asset": "U000_LEI0303_ENG.WAV"
+ "asset": "U000_TMC0212_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0103_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0110_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Select_Leia"
],
- "asset": "U000_LEI0103_ENG.WAV"
+ "asset": "U000_LEI0110_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0314_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Attack_Leia"
],
- "asset": "U000_LEI0207_ENG.WAV"
+ "asset": "U000_LEI0314_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_DEF3006_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0305_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Corrupt_Sabateur"
+ "Unit_Attack_Leia"
],
- "asset": "U000_DEF3006_ENG.WAV"
+ "asset": "U000_LEI0305_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0309_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0112_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0309_ENG.WAV"
+ "asset": "U000_LEI0112_ENG.WAV"
},
{
"id": "FILE00",
@@ -1357,120 +1416,120 @@
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_DEF3106_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0211_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Weaken_Sabateur"
+ "Unit_Move_Leia"
],
- "asset": "U000_DEF3106_ENG.WAV"
+ "asset": "U000_LEI0211_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0503_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Remove_Corruption_Leia"
+ "Unit_Move_Leia"
],
- "asset": "U000_LEI0503_ENG.WAV"
+ "asset": "U000_LEI0205_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0502_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0115_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Remove_Corruption_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0502_ENG.WAV"
+ "asset": "U000_LEI0115_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0212_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0604_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Increase_Production_Leia"
],
- "asset": "U000_LEI0212_ENG.WAV"
+ "asset": "U000_LEI0604_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027AMB_URB_CLEAR_LOOP_1.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0602_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Weather_Ambient_Clear_Urban_Loop"
+ "Unit_Increase_Production_Leia"
],
- "asset": "AMB_URB_CLEAR_LOOP_1.WAV"
+ "asset": "U000_LEI0602_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0311_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0315_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Attack_Leia"
],
- "asset": "U000_LEI0311_ENG.WAV"
+ "asset": "U000_LEI0315_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0115_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_DEF3006_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Corrupt_Sabateur"
],
- "asset": "U000_LEI0115_ENG.WAV"
+ "asset": "U000_DEF3006_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0101_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0210_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Move_Leia"
],
- "asset": "U000_LEI0101_ENG.WAV"
+ "asset": "U000_LEI0210_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0401_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0105_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Guard_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0401_ENG.WAV"
+ "asset": "U000_LEI0105_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0315_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Move_Leia"
],
- "asset": "U000_LEI0315_ENG.WAV"
+ "asset": "U000_LEI0208_ENG.WAV"
},
{
"id": "FILE00",
@@ -1489,593 +1548,1505 @@
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0603_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Increase_Production_Leia"
+ "Unit_Move_Leia"
],
- "asset": "U000_LEI0603_ENG.WAV"
+ "asset": "U000_LEI0202_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0104_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0306_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Attack_Leia"
],
- "asset": "U000_LEI0104_ENG.WAV"
+ "asset": "U000_LEI0306_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0501_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0101_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Remove_Corruption_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0501_ENG.WAV"
+ "asset": "U000_LEI0101_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027TESTUNITMOVE_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027C000_DST0102_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Gneneric_Test"
+ "EHD_Death_Star_Activate"
],
- "asset": "TESTUNITMOVE_ENG.WAV"
+ "asset": "C000_DST0102_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0108_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0103_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Select_Leia"
],
- "asset": "U000_LEI0108_ENG.WAV"
+ "asset": "U000_LEI0103_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_MCF1601_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0403_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_StarDest_MC30_Frigate"
+ "Unit_Guard_Leia"
],
- "asset": "U000_MCF1601_ENG.WAV"
+ "asset": "U000_LEI0403_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0111_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027FS_BEETLE_2.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "SFX_Anim_Beetle_Footsteps"
],
- "asset": "U000_LEI0111_ENG.WAV"
+ "asset": "FS_BEETLE_2.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0211_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0201_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Move_Leia"
],
- "asset": "U000_LEI0211_ENG.WAV"
+ "asset": "U000_LEI0201_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0110_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Move_Leia"
],
- "asset": "U000_LEI0110_ENG.WAV"
+ "asset": "U000_LEI0203_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0403_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0114_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Guard_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0403_ENG.WAV"
+ "asset": "U000_LEI0114_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0306_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027FS_BEETLE_1.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "SFX_Anim_Beetle_Footsteps"
],
- "asset": "U000_LEI0306_ENG.WAV"
+ "asset": "FS_BEETLE_1.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0308_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0304_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Attack_Leia"
],
- "asset": "U000_LEI0308_ENG.WAV"
+ "asset": "U000_LEI0304_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0112_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0301_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Attack_Leia"
],
- "asset": "U000_LEI0112_ENG.WAV"
+ "asset": "U000_LEI0301_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0301_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0503_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Remove_Corruption_Leia"
],
- "asset": "U000_LEI0301_ENG.WAV"
+ "asset": "U000_LEI0503_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0404_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0109_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Guard_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0404_ENG.WAV"
+ "asset": "U000_LEI0109_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_TMC0212_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0308_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Tie_Mauler"
+ "Unit_Attack_Leia"
],
- "asset": "U000_TMC0212_ENG.WAV"
+ "asset": "U000_LEI0308_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027EGL_STAR_VIPER_SPINNING_1.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0402_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Star_Viper_Spinning_By"
+ "Unit_Guard_Leia"
],
- "asset": "EGL_STAR_VIPER_SPINNING_1.WAV"
+ "asset": "U000_LEI0402_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0208_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0108_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0208_ENG.WAV"
+ "asset": "U000_LEI0108_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0604_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0307_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Increase_Production_Leia"
+ "Unit_Attack_Leia"
],
- "asset": "U000_LEI0604_ENG.WAV"
+ "asset": "U000_LEI0307_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027FS_BEETLE_3.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0311_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "SFX_Anim_Beetle_Footsteps"
+ "Unit_Attack_Leia"
],
- "asset": "FS_BEETLE_3.WAV"
+ "asset": "U000_LEI0311_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0109_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0102_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Select_Leia"
],
- "asset": "U000_LEI0109_ENG.WAV"
+ "asset": "U000_LEI0102_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0202_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0104_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Select_Leia"
],
- "asset": "U000_LEI0202_ENG.WAV"
+ "asset": "U000_LEI0104_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0602_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027FS_BEETLE_3.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Increase_Production_Leia"
+ "SFX_Anim_Beetle_Footsteps"
],
- "asset": "U000_LEI0602_ENG.WAV"
+ "asset": "FS_BEETLE_3.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0305_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0313_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
"Unit_Attack_Leia"
],
- "asset": "U000_LEI0305_ENG.WAV"
+ "asset": "U000_LEI0313_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_MAL0503_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0206_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Assist_Move_Missile_Launcher"
+ "Unit_Move_Leia"
],
- "asset": "U000_MAL0503_ENG.WAV"
+ "asset": "U000_LEI0206_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0601_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_ARC3104_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Increase_Production_Leia"
+ "Unit_Produce_Troops_Arc_Hammer"
],
- "asset": "U000_LEI0601_ENG.WAV"
+ "asset": "U000_ARC3104_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_ARC3106_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0312_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Complete_Troops_Arc_Hammer"
+ "Unit_Attack_Leia"
],
- "asset": "U000_ARC3106_ENG.WAV"
+ "asset": "U000_LEI0312_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027FS_BEETLE_4.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0215_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "SFX_Anim_Beetle_Footsteps"
+ "Unit_Move_Leia"
],
- "asset": "FS_BEETLE_4.WAV"
+ "asset": "U000_LEI0215_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027FS_BEETLE_1.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0107_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "SFX_Anim_Beetle_Footsteps"
+ "Unit_Select_Leia"
],
- "asset": "FS_BEETLE_1.WAV"
+ "asset": "U000_LEI0107_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0205_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0501_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Remove_Corruption_Leia"
],
- "asset": "U000_LEI0205_ENG.WAV"
+ "asset": "U000_LEI0501_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0113_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027AMB_DES_CLEAR_LOOP_1.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Weather_Ambient_Clear_Sandstorm_Loop"
],
- "asset": "U000_LEI0113_ENG.WAV"
+ "asset": "AMB_DES_CLEAR_LOOP_1.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0314_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0504_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Remove_Corruption_Leia"
],
- "asset": "U000_LEI0314_ENG.WAV"
+ "asset": "U000_LEI0504_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0304_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0502_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Unit_Remove_Corruption_Leia"
],
- "asset": "U000_LEI0304_ENG.WAV"
+ "asset": "U000_LEI0502_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0203_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_DEF3106_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "Unit_Weaken_Sabateur"
],
- "asset": "U000_LEI0203_ENG.WAV"
+ "asset": "U000_DEF3106_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027C000_DST0102_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_ARC3105_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "EHD_Death_Star_Activate"
+ "Unit_Complete_Troops_Arc_Hammer"
],
- "asset": "C000_DST0102_ENG.WAV"
+ "asset": "U000_ARC3105_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0114_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0601_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Select_Leia"
+ "Unit_Increase_Production_Leia"
],
- "asset": "U000_LEI0114_ENG.WAV"
+ "asset": "U000_LEI0601_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_ARC3104_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0204_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Produce_Troops_Arc_Hammer"
+ "Unit_Move_Leia"
],
- "asset": "U000_ARC3104_ENG.WAV"
+ "asset": "U000_LEI0204_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027FS_BEETLE_2.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027U000_LEI0207_ENG.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "SFX_Anim_Beetle_Footsteps"
+ "Unit_Move_Leia"
],
- "asset": "FS_BEETLE_2.WAV"
+ "asset": "U000_LEI0207_ENG.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_ARC3105_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027FS_BEETLE_4.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Complete_Troops_Arc_Hammer"
+ "SFX_Anim_Beetle_Footsteps"
],
- "asset": "U000_ARC3105_ENG.WAV"
+ "asset": "FS_BEETLE_4.WAV"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.AudioFilesVerifier"
],
- "message": "Audio file \u0027U000_LEI0307_ENG.WAV\u0027 could not be found.",
+ "message": "Audio file \u0027AMB_URB_CLEAR_LOOP_1.WAV\u0027 could not be found.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "Weather_Ambient_Clear_Urban_Loop"
],
- "asset": "U000_LEI0307_ENG.WAV"
+ "asset": "AMB_URB_CLEAR_LOOP_1.WAV"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
+ "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
],
- "message": "Audio file \u0027U000_LEI0402_ENG.WAV\u0027 could not be found.",
+ "message": "Could not find GUI texture \u0027i_dialogue_button_large_middle_off.tga\u0027 at location \u0027Repository\u0027.",
"severity": "Error",
"context": [
- "Unit_Guard_Leia"
+ "IDC_PLAY_FACTION_B_BUTTON_BIG",
+ "Repository"
],
- "asset": "U000_LEI0402_ENG.WAV"
+ "asset": "i_dialogue_button_large_middle_off.tga"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
+ "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
],
- "message": "Audio file \u0027U000_LEI0312_ENG.WAV\u0027 could not be found.",
+ "message": "Could not find GUI texture \u0027underworld_logo_selected.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "IDC_PLAY_FACTION_A_BUTTON_BIG",
+ "MegaTexture"
],
- "asset": "U000_LEI0312_ENG.WAV"
+ "asset": "underworld_logo_selected.tga"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
+ "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
],
- "message": "Audio file \u0027U000_LEI0210_ENG.WAV\u0027 could not be found.",
+ "message": "Could not find GUI texture \u0027underworld_logo_off.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
"context": [
- "Unit_Move_Leia"
+ "IDC_PLAY_FACTION_A_BUTTON_BIG",
+ "MegaTexture"
],
- "asset": "U000_LEI0210_ENG.WAV"
+ "asset": "underworld_logo_off.tga"
},
{
"id": "FILE00",
"verifiers": [
- "AET.ModVerify.Verifiers.AudioFilesVerifier"
+ "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
],
- "message": "Audio file \u0027U000_LEI0313_ENG.WAV\u0027 could not be found.",
+ "message": "Could not find GUI texture \u0027i_button_petro_sliver.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
"context": [
- "Unit_Attack_Leia"
+ "IDC_MENU_PETRO_LOGO",
+ "MegaTexture"
],
- "asset": "U000_LEI0313_ENG.WAV"
+ "asset": "i_button_petro_sliver.tga"
},
{
"id": "FILE00",
"verifiers": [
"AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
],
- "message": "Could not find GUI texture \u0027underworld_logo_selected.tga\u0027 at location \u0027MegaTexture\u0027.",
+ "message": "Could not find GUI texture \u0027underworld_logo_rollover.tga\u0027 at location \u0027MegaTexture\u0027.",
"severity": "Error",
"context": [
"IDC_PLAY_FACTION_A_BUTTON_BIG",
"MegaTexture"
],
- "asset": "underworld_logo_selected.tga"
+ "asset": "underworld_logo_rollover.tga"
},
{
- "id": "FILE00",
+ "id": "CMDBAR05",
"verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "message": "Could not find GUI texture \u0027i_button_petro_sliver.tga\u0027 at location \u0027MegaTexture\u0027.",
- "severity": "Error",
- "context": [
- "IDC_MENU_PETRO_LOGO",
- "MegaTexture"
+ "message": "The CommandBar component \u0027g_planet_land_forces\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_land_forces"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "asset": "i_button_petro_sliver.tga"
+ "message": "The CommandBar component \u0027g_ground_sell\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_ground_sell"
},
{
- "id": "FILE00",
+ "id": "CMDBAR05",
"verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "message": "Could not find GUI texture \u0027i_dialogue_button_large_middle_off.tga\u0027 at location \u0027Repository\u0027.",
- "severity": "Error",
- "context": [
- "IDC_PLAY_FACTION_B_BUTTON_BIG",
- "Repository"
+ "message": "The CommandBar component \u0027st_bracket_medium\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_bracket_medium"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "asset": "i_dialogue_button_large_middle_off.tga"
+ "message": "The CommandBar component \u0027b_planet_right\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "b_planet_right"
},
{
- "id": "FILE00",
+ "id": "CMDBAR04",
"verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "message": "Could not find GUI texture \u0027underworld_logo_rollover.tga\u0027 at location \u0027MegaTexture\u0027.",
- "severity": "Error",
- "context": [
- "IDC_PLAY_FACTION_A_BUTTON_BIG",
- "MegaTexture"
+ "message": "The CommandBar component \u0027g_credit_bar\u0027 is not supported by the game.",
+ "severity": "Information",
+ "context": [],
+ "asset": "g_credit_bar"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "asset": "underworld_logo_rollover.tga"
+ "message": "The CommandBar component \u0027zoomed_header_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_header_text"
},
{
- "id": "FILE00",
+ "id": "CMDBAR05",
"verifiers": [
- "AET.ModVerify.Verifiers.GuiDialogs.GuiDialogsVerifier"
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "message": "Could not find GUI texture \u0027underworld_logo_off.tga\u0027 at location \u0027MegaTexture\u0027.",
- "severity": "Error",
- "context": [
- "IDC_PLAY_FACTION_A_BUTTON_BIG",
- "MegaTexture"
+ "message": "The CommandBar component \u0027g_space_level_pips\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_space_level_pips"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
],
- "asset": "underworld_logo_off.tga"
+ "message": "The CommandBar component \u0027bribed_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "bribed_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_header_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_header_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tutorial_text_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tutorial_text_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027balance_pip\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "balance_pip"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027objective_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "objective_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027skirmish_upgrade\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "skirmish_upgrade"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027surface_mod_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "surface_mod_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_hero_health\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_hero_health"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027bribe_display\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "bribe_display"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_build\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_build"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027garrison_slot_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "garrison_slot_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_conflict\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_conflict"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_name\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_name"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027garrison_respawn_counter\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "garrison_respawn_counter"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_ability_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_ability_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_shields_medium\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_shields_medium"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_health\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_health"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_weather\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_weather"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_health_medium\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_health_medium"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_power\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_power"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_ground_level_pips\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_ground_level_pips"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027zoomed_cost_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_cost_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027bm_title_4011\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "bm_title_4011"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_planet_name\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_name"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_shields_large\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_shields_large"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_hero_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_hero_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027generic_flytext\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "generic_flytext"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027reinforcement_counter\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "reinforcement_counter"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_planet_value\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_value"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027radar_blip\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "radar_blip"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_political_control\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_political_control"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_planet_ring\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_ring"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_garrison_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_garrison_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_right_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_right_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027b_quick_ref\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "b_quick_ref"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027objective_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "objective_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_center_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_center_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_shields\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_shields"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_grab_bar\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_grab_bar"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_smuggler\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_smuggler"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_enemy_hero\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_enemy_hero"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027cs_ability_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "cs_ability_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_cost_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_cost_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_planet_ability\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_ability"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_control_group\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_control_group"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027gui_dialog_tooltip\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "gui_dialog_tooltip"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027remote_bomb_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "remote_bomb_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tutorial_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tutorial_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_space_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_space_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_bracket_large\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_bracket_large"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027zoomed_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027encyclopedia_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "encyclopedia_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027zoomed_right_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_right_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027b_beacon_t\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "b_beacon_t"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_bounty_hunter\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_bounty_hunter"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_credit_bar\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_credit_bar"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_hero\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_hero"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027bm_title_4010\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "bm_title_4010"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_planet_fleet\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_planet_fleet"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_corruption_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_corruption_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_smuggled\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_smuggled"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027help_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "help_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_bracket_small\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_bracket_small"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027objective_header_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "objective_header_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_corruption_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_corruption_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_ground_level\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_ground_level"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027lt_weather_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "lt_weather_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027cs_ability_button\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "cs_ability_button"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_radar_view\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_radar_view"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027objective_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "objective_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_back\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_back"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027zoomed_center_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_center_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_health_bar\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_health_bar"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027zoomed_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "zoomed_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027generic_collision\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "generic_collision"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_radar_blip\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_radar_blip"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_hero_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_hero_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_space_level\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_space_level"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027b_planet_left\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "b_planet_left"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_icon_land\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_icon_land"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_ground_icon\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_ground_icon"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_price\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_price"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tooltip_left_text\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tooltip_left_text"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027st_health_large\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "st_health_large"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027tactical_sell\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "tactical_sell"
+ },
+ {
+ "id": "CMDBAR05",
+ "verifiers": [
+ "AET.ModVerify.Verifiers.CommandBarVerifier"
+ ],
+ "message": "The CommandBar component \u0027g_special_ability\u0027 is not connected to a shell component.",
+ "severity": "Warning",
+ "context": [],
+ "asset": "g_special_ability"
}
]
}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Settings/CommandLine/BaseModVerifyOptions.cs b/src/ModVerify.CliApp/Settings/CommandLine/BaseModVerifyOptions.cs
index 0e5e203..36c8509 100644
--- a/src/ModVerify.CliApp/Settings/CommandLine/BaseModVerifyOptions.cs
+++ b/src/ModVerify.CliApp/Settings/CommandLine/BaseModVerifyOptions.cs
@@ -21,9 +21,9 @@ internal abstract class BaseModVerifyOptions
public string? Suppressions { get; init; }
[Option("path", SetName = "autoDetection", Required = false, Default = null,
- HelpText = "Specifies the path to verify. The path may be a game or mod. The application will try to find all necessary sub-mods or base games itself. " +
+ HelpText = "Specifies the path to verify. The path may be a game or mod. The application will try to find all necessary sub-mods and base games itself. " +
"The argument cannot be combined with any of --mods, --game or --fallbackGame")]
- public string? AutoPath { get; init; }
+ public string? TargetPath { get; init; }
[Option("mods", SetName = "manualPaths", Required = false, Default = null, Separator = ';',
HelpText = "The path of the mod to verify. To support submods, multiple paths can be separated using the ';' (semicolon) character. " +
@@ -41,10 +41,10 @@ internal abstract class BaseModVerifyOptions
public string? FallbackGamePath { get; init; }
- [Option("type", Required = false, Default = null,
- HelpText = "The game type of the mod that shall be verified. Skip this value to auto-determine the type. Valid values are 'Eaw' and 'Foc'. " +
+ [Option("engine", Required = false, Default = null,
+ HelpText = "The game engine of the target that shall be verified. Skip this value to auto-determine the type. Valid values are 'Eaw' and 'Foc'. " +
"This argument is required, if the first mod of '--mods' points to a directory outside of the common folder hierarchy (e.g, /MODS/MOD_NAME or /32470/WORKSHOP_ID")]
- public GameEngineType? GameType { get; init; }
+ public GameEngineType? Engine { get; init; }
[Option("additionalFallbackPaths", Required = false, Separator = ';',
diff --git a/src/ModVerify.CliApp/Settings/CommandLine/VerifyVerbOption.cs b/src/ModVerify.CliApp/Settings/CommandLine/VerifyVerbOption.cs
index 97f1536..9581a9c 100644
--- a/src/ModVerify.CliApp/Settings/CommandLine/VerifyVerbOption.cs
+++ b/src/ModVerify.CliApp/Settings/CommandLine/VerifyVerbOption.cs
@@ -20,17 +20,19 @@ internal sealed class VerifyVerbOption : BaseModVerifyOptions
public bool FailFast { get; init; }
[Option("minFailSeverity", Required = false, Default = null,
- HelpText = "When set, the application return with an error, if any finding has at least the specified severity value.")]
+ HelpText = "When set, the application returns with an error, if any finding has at least the specified severity value.")]
public VerificationSeverity? MinimumFailureSeverity { get; set; }
[Option("ignoreAsserts", Required = false,
HelpText = "When this flag is present, the application will not report engine assertions.")]
public bool IgnoreAsserts { get; init; }
+
[Option("baseline", SetName = "baselineSelection", Required = false,
HelpText = "Path to a JSON baseline file. Cannot be used together with --searchBaseline.")]
public string? Baseline { get; init; }
+ // TODO: Ignore, if baseline is set
[Option("searchBaseline", SetName = "baselineSelection", Required = false,
HelpText = "When set, the application will search for baseline files and use them for verification. Cannot be used together with --baseline")]
public bool SearchBaselineLocally { get; init; }
diff --git a/src/ModVerify.CliApp/Settings/GameInstallationsSettings.cs b/src/ModVerify.CliApp/Settings/GameInstallationsSettings.cs
deleted file mode 100644
index 00bc4f0..0000000
--- a/src/ModVerify.CliApp/Settings/GameInstallationsSettings.cs
+++ /dev/null
@@ -1,28 +0,0 @@
-using System.Collections.Generic;
-using System.Diagnostics.CodeAnalysis;
-using PG.StarWarsGame.Engine;
-
-namespace AET.ModVerify.App.Settings;
-
-internal sealed record GameInstallationsSettings
-{
- public bool Interactive => string.IsNullOrEmpty(AutoPath) && ModPaths.Count == 0 && string.IsNullOrEmpty(GamePath);
-
- [MemberNotNullWhen(true, nameof(AutoPath))]
- public bool UseAutoDetection => !string.IsNullOrEmpty(AutoPath);
-
- [MemberNotNullWhen(true, nameof(GamePath))]
- public bool ManualSetup => !string.IsNullOrEmpty(GamePath);
-
- public string? AutoPath { get; init; }
-
- public IList ModPaths { get; init; } = [];
-
- public string? GamePath { get; init; }
-
- public string? FallbackGamePath { get; init; }
-
- public IList AdditionalFallbackPaths { get; init; } = [];
-
- public GameEngineType? EngineType { get; init; }
-}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Settings/ModVerifyAppSettings.cs b/src/ModVerify.CliApp/Settings/ModVerifyAppSettings.cs
index 3376354..0419f33 100644
--- a/src/ModVerify.CliApp/Settings/ModVerifyAppSettings.cs
+++ b/src/ModVerify.CliApp/Settings/ModVerifyAppSettings.cs
@@ -6,13 +6,13 @@ namespace AET.ModVerify.App.Settings;
internal sealed class ModVerifyAppSettings
{
- public bool Interactive => GameInstallationsSettings.Interactive;
+ public bool Interactive => VerificationTargetSettings.Interactive;
public required VerifyPipelineSettings VerifyPipelineSettings { get; init; }
public required ModVerifyReportSettings ReportSettings { get; init; }
- public required GameInstallationsSettings GameInstallationsSettings { get; init; }
+ public required VerificationTargetSettings VerificationTargetSettings { get; init; }
public VerificationSeverity? AppThrowsOnMinimumSeverity { get; init; }
@@ -20,4 +20,30 @@ internal sealed class ModVerifyAppSettings
public bool CreateNewBaseline => !string.IsNullOrEmpty(NewBaselinePath);
public string? NewBaselinePath { get; init; }
+}
+
+
+internal enum AppMode
+{
+ Verify,
+ Baseline
+}
+
+internal abstract class ModVerifyAppSettingsBase
+{
+ public abstract AppMode Mode { get; }
+ public bool IsInteractive => VerificationTargetSettings.Interactive;
+ public required VerificationTargetSettings VerificationTargetSettings { get; init; }
+}
+
+internal sealed class VerifyAppSettings : ModVerifyAppSettingsBase
+{
+ public override AppMode Mode => AppMode.Verify;
+ public VerificationSeverity? AppThrowsOnMinimumSeverity { get; init; }
+}
+
+internal sealed class BaselineAppSettings : ModVerifyAppSettingsBase
+{
+ public override AppMode Mode => AppMode.Baseline;
+ public required string NewBaselinePath { get; init; }
}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Settings/SettingsBuilder.cs b/src/ModVerify.CliApp/Settings/SettingsBuilder.cs
index 3c5535f..8a31301 100644
--- a/src/ModVerify.CliApp/Settings/SettingsBuilder.cs
+++ b/src/ModVerify.CliApp/Settings/SettingsBuilder.cs
@@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO.Abstractions;
using AET.ModVerify.App.Settings.CommandLine;
-using AET.ModVerify.App.Utilities;
using AET.ModVerify.Pipeline;
using AET.ModVerify.Reporting;
using AET.ModVerify.Settings;
@@ -44,7 +43,7 @@ private ModVerifyAppSettings BuildFromVerifyVerb(VerifyVerbOption verifyOptions)
}
},
AppThrowsOnMinimumSeverity = verifyOptions.MinimumFailureSeverity,
- GameInstallationsSettings = BuildInstallationSettings(verifyOptions),
+ VerificationTargetSettings = BuildInstallationSettings(verifyOptions),
ReportSettings = BuildReportSettings(verifyOptions),
};
@@ -56,7 +55,7 @@ private ModVerifyAppSettings BuildFromVerifyVerb(VerifyVerbOption verifyOptions)
if (minFailSeverity == null)
{
_logger?.LogWarning(ModVerifyConstants.ConsoleEventId,
- "Verification is configured to fail fast but 'minFailSeverity' is not specified. Using severity '{Info}'.", VerificationSeverity.Information);
+ "Verification is configured to fail fast but 'minFailSeverity' is not specified. Using severity '{Severity}'.", VerificationSeverity.Information);
minFailSeverity = VerificationSeverity.Information;
}
@@ -85,7 +84,7 @@ private ModVerifyAppSettings BuildFromCreateBaselineVerb(CreateBaselineVerbOptio
FailFast = false,
},
AppThrowsOnMinimumSeverity = null,
- GameInstallationsSettings = BuildInstallationSettings(baselineVerb),
+ VerificationTargetSettings = BuildInstallationSettings(baselineVerb),
ReportSettings = BuildReportSettings(baselineVerb),
NewBaselinePath = baselineVerb.OutputFile,
};
@@ -107,11 +106,11 @@ static bool SearchLocally(BaseModVerifyOptions o)
{
if (o is not VerifyVerbOption v)
return false;
- return v.SearchBaselineLocally || v.LaunchedWithoutArguments();
+ return v.SearchBaselineLocally;
}
}
- private GameInstallationsSettings BuildInstallationSettings(BaseModVerifyOptions options)
+ private VerificationTargetSettings BuildInstallationSettings(BaseModVerifyOptions options)
{
var modPaths = new List();
if (options.ModPaths is not null)
@@ -142,18 +141,18 @@ private GameInstallationsSettings BuildInstallationSettings(BaseModVerifyOptions
if (!string.IsNullOrEmpty(gamePath) && !string.IsNullOrEmpty(options.FallbackGamePath))
fallbackGamePath = _fileSystem.Path.GetFullPath(options.FallbackGamePath!);
- var autoPath = options.AutoPath;
- if (!string.IsNullOrEmpty(autoPath))
- autoPath = _fileSystem.Path.GetFullPath(autoPath!);
+ var targetPath = options.TargetPath;
+ if (!string.IsNullOrEmpty(targetPath))
+ targetPath = _fileSystem.Path.GetFullPath(targetPath!);
- return new GameInstallationsSettings
+ return new VerificationTargetSettings
{
- AutoPath = autoPath,
+ TargetPath = targetPath,
ModPaths = modPaths,
GamePath = gamePath,
FallbackGamePath = fallbackGamePath,
AdditionalFallbackPaths = fallbackPaths,
- EngineType = options.GameType
+ Engine = options.Engine
};
}
}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Settings/VerificationTargetSettings.cs b/src/ModVerify.CliApp/Settings/VerificationTargetSettings.cs
new file mode 100644
index 0000000..b5e1a40
--- /dev/null
+++ b/src/ModVerify.CliApp/Settings/VerificationTargetSettings.cs
@@ -0,0 +1,28 @@
+using System.Collections.Generic;
+using System.Diagnostics.CodeAnalysis;
+using PG.StarWarsGame.Engine;
+
+namespace AET.ModVerify.App.Settings;
+
+internal sealed record VerificationTargetSettings
+{
+ public bool Interactive => string.IsNullOrEmpty(TargetPath) && ModPaths.Count == 0 && string.IsNullOrEmpty(GamePath) && string.IsNullOrEmpty(FallbackGamePath);
+
+ [MemberNotNullWhen(true, nameof(TargetPath))]
+ public bool UseAutoDetection => !string.IsNullOrEmpty(TargetPath) && ModPaths.Count == 0 && string.IsNullOrEmpty(GamePath) && string.IsNullOrEmpty(FallbackGamePath);
+
+ [MemberNotNullWhen(true, nameof(GamePath))]
+ public bool ManualSetup => !string.IsNullOrEmpty(GamePath);
+
+ public string? TargetPath { get; init; }
+
+ public IReadOnlyList ModPaths { get; init; } = [];
+
+ public string? GamePath { get; init; }
+
+ public string? FallbackGamePath { get; init; }
+
+ public IReadOnlyList AdditionalFallbackPaths { get; init; } = [];
+
+ public GameEngineType? Engine { get; init; }
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/TargetSelectors/AutomaticSelector.cs b/src/ModVerify.CliApp/TargetSelectors/AutomaticSelector.cs
new file mode 100644
index 0000000..f6b2b0c
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/AutomaticSelector.cs
@@ -0,0 +1,201 @@
+using AET.ModVerify.App.GameFinder;
+using AET.ModVerify.App.Settings;
+using AET.ModVerify.App.Utilities;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Infrastructure;
+using PG.StarWarsGame.Infrastructure.Games;
+using PG.StarWarsGame.Infrastructure.Mods;
+using PG.StarWarsGame.Infrastructure.Services;
+using PG.StarWarsGame.Infrastructure.Services.Detection;
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+using System.Globalization;
+using System.IO.Abstractions;
+using System.Linq;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal class AutomaticSelector(IServiceProvider serviceProvider) : VerificationTargetSelectorBase(serviceProvider)
+{
+ private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService();
+
+ internal override SelectionResult SelectTarget(VerificationTargetSettings settings)
+ {
+ if (!settings.UseAutoDetection)
+ throw new ArgumentException("wrong settings format provided.", nameof(settings));
+
+ var targetPath = settings.TargetPath;
+ if (!_fileSystem.Directory.Exists(targetPath))
+ {
+ Logger?.LogError(ModVerifyConstants.ConsoleEventId, "The specified path '{Path}' does not exist.", targetPath);
+ throw new TargetNotFoundException(targetPath);
+ }
+
+ var engine = settings.Engine;
+
+ GameFinderResult finderResult;
+ try
+ {
+ var finderSettings = new GameFinderSettings
+ {
+ Engine = engine,
+ InitMods = true,
+ SearchFallbackGame = true
+ };
+ finderResult = GameFinderService.FindGamesFromPathOrGlobal(targetPath, finderSettings);
+ }
+ catch (GameNotFoundException)
+ {
+ Logger?.LogError(ModVerifyConstants.ConsoleEventId,
+ "Unable to find games based of the specified target path '{Path}'. Consider specifying all paths manually.", targetPath);
+ throw;
+ }
+
+ // In a Steam scenario, there is a chance that the user specified a FoC targetPath,
+ // but requested EaW engine. This does not make sense, and we need to check against this.
+ if (finderResult.Game.Platform == GamePlatform.SteamGold && engine is GameEngineType.Eaw)
+ {
+ var targetIsFoc = GameFinderService.TryFindGame(targetPath,
+ new GameFinderSettings { Engine = GameEngineType.Foc, InitMods = false, SearchFallbackGame = false },
+ out _);
+ if (targetIsFoc)
+ ThrowEngineNotSupported(engine.Value, targetPath);
+ }
+
+ if (engine.HasValue)
+ {
+ if (finderResult.Game.Type.ToEngineType() != engine.Value)
+ {
+ if (finderResult.FallbackGame?.Type.ToEngineType() != engine)
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ }
+
+
+ GameLocations locations;
+
+ var targetObject = GetAttachedModOrGame(finderResult, targetPath, engine);
+
+ if (targetObject is not null)
+ {
+ var actualType = targetObject.Game.Type;
+ Debug.Assert(IsEngineTypeSupported(engine, actualType));
+ engine ??= actualType.ToEngineType();
+ locations = GetLocations(targetObject, finderResult.FallbackGame, settings.AdditionalFallbackPaths);
+ }
+ else
+ {
+ if (!engine.HasValue)
+ throw new ArgumentException("Game engine not specified. Use --engine argument to set it.");
+
+ Logger?.LogDebug("The requested mod at '{TargetPath}' is detached from its games.", targetPath);
+
+ // The path is a detached mod, that exists on a different location than the game.
+ locations = GetDetachedModLocations(targetPath, finderResult, engine.Value, settings.AdditionalFallbackPaths, out var mod);
+ targetObject = mod;
+ }
+
+ return new(locations, engine.Value, targetObject);
+ }
+
+ private IPhysicalPlayableObject? GetAttachedModOrGame(GameFinderResult finderResult, string targetPath, GameEngineType? requestedEngineType)
+ {
+ var targetFullPath = _fileSystem.Path.GetFullPath(targetPath);
+
+ IPhysicalPlayableObject? target = null;
+
+ // If the target is the game directory itself.
+ if (targetFullPath.Equals(finderResult.Game.Directory.FullName, StringComparison.OrdinalIgnoreCase))
+ target = finderResult.Game;
+ else if (finderResult.FallbackGame is not null && targetFullPath.Equals(finderResult.FallbackGame.Directory.FullName, StringComparison.OrdinalIgnoreCase))
+ {
+ // The game detection identified both Foc and Eaw because either Steam is installed or requestedEngineType was not specified.
+ // The requested path points to a EaW installation.
+ Debug.Assert(finderResult.FallbackGame.Type is GameType.Eaw);
+ target = finderResult.FallbackGame;
+ }
+
+ target ??= GetMatchingModFromGame(finderResult.Game, targetFullPath, requestedEngineType) ??
+ GetMatchingModFromGame(finderResult.FallbackGame, targetFullPath, requestedEngineType);
+
+
+ if (target is not null)
+ {
+ if (!IsEngineTypeSupported(requestedEngineType, target.Game.Type))
+ ThrowEngineNotSupported(requestedEngineType.Value, targetPath);
+ }
+
+ return target;
+ }
+
+ private GameLocations GetDetachedModLocations(
+ string modPath,
+ GameFinderResult gameResult,
+ GameEngineType requestedGameEngine,
+ IReadOnlyList additionalFallbackPaths,
+ out IPhysicalMod mod)
+ {
+ var game = GetTargetGame(gameResult, requestedGameEngine);
+ Debug.Assert(game is not null);
+
+ var modFinder = ServiceProvider.GetRequiredService();
+ var modRef = modFinder.FindMods(game, _fileSystem.DirectoryInfo.New(modPath)).FirstOrDefault();
+
+ if (modRef is null)
+ ThrowEngineNotSupported(requestedGameEngine, modPath);
+
+ var modFactory = ServiceProvider.GetRequiredService();
+ mod = modFactory.CreatePhysicalMod(game, modRef, CultureInfo.InvariantCulture);
+
+ game.AddMod(mod);
+
+ mod.ResolveDependencies();
+
+ return GetLocations(mod, gameResult.FallbackGame, additionalFallbackPaths);
+ }
+
+ private static IPhysicalMod? GetMatchingModFromGame(IGame? game, string modPath, GameEngineType? requestedEngineType)
+ {
+ if (game is null || !IsEngineTypeSupported(requestedEngineType, game.Type))
+ return null;
+
+ foreach (var mod in game.Game.Mods)
+ {
+ if (mod is not IPhysicalMod physicalMod)
+ continue;
+
+ if (physicalMod.Directory.FullName.Equals(modPath, StringComparison.OrdinalIgnoreCase))
+ return physicalMod;
+ }
+
+ return null;
+ }
+
+ private static IGame? GetTargetGame(GameFinderResult finderResult, GameEngineType? requestedEngine)
+ {
+ if (!requestedEngine.HasValue)
+ return null;
+ if (finderResult.Game.Type.ToEngineType() == requestedEngine)
+ return finderResult.Game;
+ if (finderResult.FallbackGame is not null && finderResult.FallbackGame.Type.ToEngineType() == requestedEngine)
+ return finderResult.FallbackGame;
+ return null;
+ }
+
+ private static bool IsEngineTypeSupported([NotNullWhen(false)] GameEngineType? requestedEngineType, GameType actualGameType)
+ {
+ return !requestedEngineType.HasValue || actualGameType.ToEngineType() == requestedEngineType;
+ }
+
+ [DoesNotReturn]
+ private static void ThrowEngineNotSupported(GameEngineType requested, string targetPath)
+ {
+ throw new ArgumentException($"The specified game engine '{requested}' does not match engine of the verification target '{targetPath}'.");
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs b/src/ModVerify.CliApp/TargetSelectors/ConsoleSelector.cs
similarity index 83%
rename from src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs
rename to src/ModVerify.CliApp/TargetSelectors/ConsoleSelector.cs
index c776d6d..8c54cef 100644
--- a/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs
+++ b/src/ModVerify.CliApp/TargetSelectors/ConsoleSelector.cs
@@ -5,22 +5,21 @@
using AET.ModVerify.App.Settings;
using AET.ModVerify.App.Utilities;
using AnakinRaW.ApplicationBase;
-using PG.StarWarsGame.Engine;
using PG.StarWarsGame.Infrastructure;
using PG.StarWarsGame.Infrastructure.Games;
using PG.StarWarsGame.Infrastructure.Mods;
-namespace AET.ModVerify.App.ModSelectors;
+namespace AET.ModVerify.App.TargetSelectors;
-internal class ConsoleModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider)
+internal class ConsoleSelector(IServiceProvider serviceProvider) : VerificationTargetSelectorBase(serviceProvider)
{
- public override GameLocations Select(GameInstallationsSettings settings, out IPhysicalPlayableObject targetObject,
- out GameEngineType? actualEngineType)
+ internal override SelectionResult SelectTarget(VerificationTargetSettings settings)
{
- var gameResult = GameFinderService.FindGames();
- targetObject = SelectPlayableObject(gameResult);
- actualEngineType = targetObject.Game.Type.ToEngineType();
- return GetLocations(targetObject, gameResult, settings.AdditionalFallbackPaths);
+ var gameResult = GameFinderService.FindGames(GameFinderSettings.Default);
+ var targetObject = SelectPlayableObject(gameResult);
+ var engine = targetObject.Game.Type.ToEngineType();
+ var locations = GetLocations(targetObject, gameResult.FallbackGame, settings.AdditionalFallbackPaths);
+ return new(locations, engine, targetObject);
}
private static IPhysicalPlayableObject SelectPlayableObject(GameFinderResult finderResult)
diff --git a/src/ModVerify.CliApp/TargetSelectors/IVerificationTargetSelector.cs b/src/ModVerify.CliApp/TargetSelectors/IVerificationTargetSelector.cs
new file mode 100644
index 0000000..6d452e8
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/IVerificationTargetSelector.cs
@@ -0,0 +1,8 @@
+using AET.ModVerify.App.Settings;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal interface IVerificationTargetSelector
+{
+ VerificationTarget Select(VerificationTargetSettings settings);
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/TargetSelectors/ManualSelector.cs b/src/ModVerify.CliApp/TargetSelectors/ManualSelector.cs
new file mode 100644
index 0000000..f963b4f
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/ManualSelector.cs
@@ -0,0 +1,73 @@
+using System;
+using System.Globalization;
+using System.Linq;
+using AET.ModVerify.App.GameFinder;
+using AET.ModVerify.App.Settings;
+using Microsoft.Extensions.DependencyInjection;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Infrastructure;
+using PG.StarWarsGame.Infrastructure.Games;
+using PG.StarWarsGame.Infrastructure.Services;
+using PG.StarWarsGame.Infrastructure.Services.Detection;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal class ManualSelector(IServiceProvider serviceProvider) : VerificationTargetSelectorBase(serviceProvider)
+{
+ internal override SelectionResult SelectTarget(VerificationTargetSettings settings)
+ {
+ if (string.IsNullOrEmpty(settings.GamePath))
+ throw new ArgumentException("Argument --game must be set.");
+ if (!settings.Engine.HasValue)
+ throw new ArgumentException("Unable to determine game type. Use --engine argument to set the game type.");
+
+ var engine = settings.Engine.Value;
+
+ var gameLocations = new GameLocations(
+ settings.ModPaths.ToList(),
+ settings.GamePath!,
+ GetFallbackPaths(settings.FallbackGamePath, settings.AdditionalFallbackPaths).ToList());
+
+
+ // For the manual selector the whole game and mod detection is optional.
+ // This allows user to use the application for unusual scenarios,
+ // not known to the detection service.
+ if (!GameFinderService.TryFindGame(gameLocations.GamePath,
+ new GameFinderSettings { Engine = engine, InitMods = false, SearchFallbackGame = false },
+ out var game))
+ {
+ // TODO: Log
+ }
+
+ // If the fallback game path is specified we simply try to detect the game and report a warning to the user if not found.
+ var fallbackGamePath = settings.FallbackGamePath;
+ if (!string.IsNullOrEmpty(fallbackGamePath))
+ {
+
+ if (!GameFinderService.TryFindGame(fallbackGamePath,
+ new GameFinderSettings { InitMods = false, SearchFallbackGame = false },
+ out _))
+ {
+ // TODO: Log
+ }
+ }
+
+ var target = TryGetPlayableObject(game, gameLocations.ModPaths.FirstOrDefault());
+ return new SelectionResult(gameLocations, engine, target);
+ }
+
+ private IPhysicalPlayableObject? TryGetPlayableObject(IGame? game, string? modPath)
+ {
+ if (game is null)
+ return null;
+ if (string.IsNullOrEmpty(modPath))
+ return game;
+
+ var modFinder = ServiceProvider.GetRequiredService();
+ var modFactory = ServiceProvider.GetRequiredService();
+
+ var mods = modFinder.FindMods(game, FileSystem.DirectoryInfo.New(modPath));
+ var mod = modFactory.CreatePhysicalMod(game, mods.First(), CultureInfo.InvariantCulture);
+ return mod;
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/TargetSelectors/TargetNotFoundException.cs b/src/ModVerify.CliApp/TargetSelectors/TargetNotFoundException.cs
new file mode 100644
index 0000000..d6b052e
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/TargetNotFoundException.cs
@@ -0,0 +1,6 @@
+using System.IO;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal class TargetNotFoundException(string path)
+ : DirectoryNotFoundException($"The target path '{path}' does not exist");
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorBase.cs b/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorBase.cs
new file mode 100644
index 0000000..7d353fa
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorBase.cs
@@ -0,0 +1,116 @@
+using System;
+using System.Collections.Generic;
+using System.IO.Abstractions;
+using System.Linq;
+using AET.ModVerify.App.GameFinder;
+using AET.ModVerify.App.Settings;
+using Microsoft.Extensions.DependencyInjection;
+using Microsoft.Extensions.Logging;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Infrastructure;
+using PG.StarWarsGame.Infrastructure.Games;
+using PG.StarWarsGame.Infrastructure.Mods;
+using PG.StarWarsGame.Infrastructure.Services.Dependencies;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal abstract class VerificationTargetSelectorBase : IVerificationTargetSelector
+{
+ internal sealed record SelectionResult(
+ GameLocations Locations,
+ GameEngineType Engine,
+ IPhysicalPlayableObject? Target);
+
+ protected readonly ILogger? Logger;
+ protected readonly GameFinderService GameFinderService;
+ protected readonly IServiceProvider ServiceProvider;
+ protected readonly IFileSystem FileSystem;
+
+ protected VerificationTargetSelectorBase(IServiceProvider serviceProvider)
+ {
+ ServiceProvider = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
+ Logger = serviceProvider.GetService()?.CreateLogger(GetType());
+ GameFinderService = new GameFinderService(serviceProvider);
+ FileSystem = serviceProvider.GetRequiredService();
+ }
+
+ public VerificationTarget Select(VerificationTargetSettings settings)
+ {
+ var selectedTarget = SelectTarget(settings);
+
+ return new VerificationTarget
+ {
+ Location = selectedTarget.Locations,
+ Engine = selectedTarget.Engine,
+ Name = GetTargetName(selectedTarget.Target, selectedTarget.Locations),
+ Version = GetTargetVersion(selectedTarget.Target)
+ };
+ }
+
+
+ internal abstract SelectionResult SelectTarget(VerificationTargetSettings settings);
+
+
+ protected GameLocations GetLocations(
+ IPhysicalPlayableObject target,
+ IGame? fallbackGame,
+ IReadOnlyList additionalFallbackPaths)
+ {
+ var fallbacks = GetFallbackPaths(target, fallbackGame, additionalFallbackPaths);
+ var modPaths = GetModPaths(target);
+ return new GameLocations(modPaths, target.Game.Directory.FullName, fallbacks);
+ }
+
+ private static IReadOnlyList GetFallbackPaths(IPhysicalPlayableObject target, IGame? fallbackGame, IReadOnlyList additionalFallbackPaths)
+ {
+ var coercedFallbackGame = fallbackGame;
+ if (target is IGame tGame && tGame.Equals(fallbackGame))
+ coercedFallbackGame = null;
+ else if (target.Game.Equals(fallbackGame))
+ coercedFallbackGame = null;
+ return GetFallbackPaths(coercedFallbackGame?.Directory.FullName, additionalFallbackPaths);
+ }
+
+
+ protected static IReadOnlyList GetFallbackPaths(string? fallbackGame, IReadOnlyList additionalFallbackPaths)
+ {
+ var fallbacks = new List();
+ if (fallbackGame is not null)
+ fallbacks.Add(fallbackGame);
+ foreach (var fallback in additionalFallbackPaths)
+ fallbacks.Add(fallback);
+ return fallbacks;
+ }
+
+
+ private IReadOnlyList GetModPaths(IPhysicalPlayableObject modOrGame)
+ {
+ if (modOrGame is not IMod mod)
+ return [];
+
+ var traverser = ServiceProvider.GetRequiredService();
+ return traverser.Traverse(mod)
+ .OfType().Select(x => x.Directory.FullName)
+ .ToList();
+ }
+
+ protected static string GetTargetName(IPhysicalPlayableObject? targetObject, GameLocations gameLocations)
+ {
+ if (targetObject is not null)
+ return targetObject.Name;
+
+ // TODO: Reuse name beautifier from GameInfrastructure lib
+ var mod = gameLocations.ModPaths.FirstOrDefault();
+ return mod ?? gameLocations.GamePath;
+ }
+
+ protected static string? GetTargetVersion(IPhysicalPlayableObject? targetObject)
+ {
+ if (targetObject is null)
+ return null;
+
+ // TODO: Implement version retrieval from targetObject if possible
+ return null;
+ }
+
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorFactory.cs b/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorFactory.cs
new file mode 100644
index 0000000..5e106eb
--- /dev/null
+++ b/src/ModVerify.CliApp/TargetSelectors/VerificationTargetSelectorFactory.cs
@@ -0,0 +1,18 @@
+using System;
+using AET.ModVerify.App.Settings;
+
+namespace AET.ModVerify.App.TargetSelectors;
+
+internal sealed class VerificationTargetSelectorFactory(IServiceProvider serviceProvider)
+{
+ public IVerificationTargetSelector CreateSelector(VerificationTargetSettings settings)
+ {
+ if (settings.Interactive)
+ return new ConsoleSelector(serviceProvider);
+ if (settings.UseAutoDetection)
+ return new AutomaticSelector(serviceProvider);
+ if (settings.ManualSetup)
+ return new ManualSelector(serviceProvider);
+ throw new ArgumentException("Unknown option configuration provided.");
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify.CliApp/Utilities/ExtensionMethods.cs b/src/ModVerify.CliApp/Utilities/ExtensionMethods.cs
index b2e7ab0..fb3c68a 100644
--- a/src/ModVerify.CliApp/Utilities/ExtensionMethods.cs
+++ b/src/ModVerify.CliApp/Utilities/ExtensionMethods.cs
@@ -10,12 +10,12 @@ internal static class ExtensionMethods
{
public static GameEngineType ToEngineType(this GameType type)
{
- return type == GameType.Foc ? GameEngineType.Foc : GameEngineType.Eaw;
+ return (GameEngineType)(int)type;
}
public static GameType FromEngineType(this GameEngineType type)
{
- return type == GameEngineType.Foc ? GameType.Foc : GameType.Eaw;
+ return (GameType)(int)type;
}
extension(ApplicationEnvironment modVerifyEnvironment)
diff --git a/src/ModVerify/ModVerify.csproj b/src/ModVerify/ModVerify.csproj
index 427458d..634dbf7 100644
--- a/src/ModVerify/ModVerify.csproj
+++ b/src/ModVerify/ModVerify.csproj
@@ -25,18 +25,18 @@
-
+
-
+
-
-
-
-
+
+
+
+
@@ -51,8 +51,4 @@
-
-
-
-
diff --git a/src/ModVerify/Pipeline/GameVerifierPipelineStep.cs b/src/ModVerify/Pipeline/GameVerifierPipelineStep.cs
index 6405dbd..e83cb25 100644
--- a/src/ModVerify/Pipeline/GameVerifierPipelineStep.cs
+++ b/src/ModVerify/Pipeline/GameVerifierPipelineStep.cs
@@ -5,6 +5,7 @@
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
+using System.Threading.Tasks;
using AET.ModVerify.Pipeline.Progress;
namespace AET.ModVerify.Pipeline;
@@ -22,18 +23,19 @@ public sealed class GameVerifierPipelineStep(
public long Size => 1;
- protected override void RunCore(CancellationToken token)
+ protected override Task RunCoreAsync(CancellationToken token)
{
try
{
Logger?.LogDebug("Running verifier '{Name}'...", GameVerifier.FriendlyName);
ReportProgress(new ProgressEventArgs(0.0, "Started"));
-
+
GameVerifier.Progress += OnVerifyProgress;
GameVerifier.Verify(token);
Logger?.LogDebug("Finished verifier '{Name}'", GameVerifier.FriendlyName);
ReportProgress(new ProgressEventArgs(1.0, "Finished"));
+ return Task.CompletedTask;
}
finally
{
diff --git a/src/ModVerify/Pipeline/GameVerifyPipeline.cs b/src/ModVerify/Pipeline/GameVerifyPipeline.cs
index 810651a..8e521eb 100644
--- a/src/ModVerify/Pipeline/GameVerifyPipeline.cs
+++ b/src/ModVerify/Pipeline/GameVerifyPipeline.cs
@@ -1,7 +1,7 @@
-using AET.ModVerify.Reporting;
+using AET.ModVerify.Pipeline.Progress;
+using AET.ModVerify.Reporting;
using AET.ModVerify.Reporting.Settings;
using AET.ModVerify.Settings;
-using AET.ModVerify.Utilities;
using AET.ModVerify.Verifiers;
using AnakinRaW.CommonUtilities.SimplePipeline;
using AnakinRaW.CommonUtilities.SimplePipeline.Runners;
@@ -12,94 +12,102 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
-using AET.ModVerify.Pipeline.Progress;
+using AET.ModVerify.Utilities;
+using Microsoft.Extensions.DependencyInjection;
namespace AET.ModVerify.Pipeline;
-public sealed class GameVerifyPipeline : AnakinRaW.CommonUtilities.SimplePipeline.Pipeline
+public sealed class GameVerifyPipeline : StepRunnerPipelineBase
{
- private readonly List _verifiers = new();
- private readonly List _verificationSteps = new();
- private readonly StepRunnerBase _verifyRunner;
-
- private readonly IStarWarsGameEngine _gameEngine;
- private readonly IGameEngineErrorCollection _engineErrors;
+ private readonly List _verifiers = [];
+ private readonly List _verificationSteps = [];
+ private readonly ConcurrentGameEngineErrorReporter _engineErrorReporter = new();
+ private readonly VerificationTarget _verificationTarget;
private readonly VerifyPipelineSettings _pipelineSettings;
private readonly GlobalVerifyReportSettings _reportSettings;
-
private readonly IVerifyProgressReporter _progressReporter;
-
- protected override bool FailFast { get; }
+ private readonly IGameEngineInitializationReporter? _engineInitializationReporter;
+ private readonly IPetroglyphStarWarsGameEngineService _gameEngineService;
+ private readonly ILogger? _logger;
+ private AggregatedVerifyProgressReporter? _aggregatedVerifyProgressReporter;
public IReadOnlyCollection FilteredErrors { get; private set; } = [];
-
+
public GameVerifyPipeline(
- IStarWarsGameEngine gameEngine,
- IGameEngineErrorCollection engineErrors,
- VerifyPipelineSettings pipelineSettings,
+ VerificationTarget verificationTarget,
+ VerifyPipelineSettings pipelineSettings,
GlobalVerifyReportSettings reportSettings,
IVerifyProgressReporter progressReporter,
+ IGameEngineInitializationReporter? engineInitializationReporter,
IServiceProvider serviceProvider) : base(serviceProvider)
{
- _gameEngine = gameEngine ?? throw new ArgumentNullException(nameof(gameEngine));
- _engineErrors = engineErrors ?? throw new ArgumentNullException(nameof(gameEngine));
+ _verificationTarget = verificationTarget ?? throw new ArgumentNullException(nameof(verificationTarget));
_pipelineSettings = pipelineSettings ?? throw new ArgumentNullException(nameof(pipelineSettings));
_reportSettings = reportSettings ?? throw new ArgumentNullException(nameof(reportSettings));
_progressReporter = progressReporter ?? throw new ArgumentNullException(nameof(progressReporter));
-
- if (pipelineSettings.ParallelVerifiers is < 0 or > 64)
- throw new ArgumentException("_pipelineSettings has invalid parallel worker number.", nameof(pipelineSettings));
-
- if (pipelineSettings.ParallelVerifiers == 1)
- _verifyRunner = new SequentialStepRunner(serviceProvider);
- else
- _verifyRunner = new ParallelStepRunner(pipelineSettings.ParallelVerifiers, serviceProvider);
+ _engineInitializationReporter = engineInitializationReporter;
+ _gameEngineService = serviceProvider.GetRequiredService();
+ _logger = serviceProvider.GetService()?.CreateLogger(GetType());
FailFast = pipelineSettings.FailFast;
}
- protected override Task PrepareCoreAsync()
+ protected override AsyncStepRunner CreateRunner()
{
- _verifiers.Clear();
-
- AddStep(new GameEngineErrorCollector(_engineErrors, _gameEngine, _pipelineSettings.GameVerifySettings, ServiceProvider));
-
- foreach (var gameVerificationStep in CreateVerificationSteps(_gameEngine))
- AddStep(gameVerificationStep);
-
- return Task.FromResult(true);
+ var requestedRunnerCount = _pipelineSettings.ParallelVerifiers;
+ return requestedRunnerCount switch
+ {
+ < 0 or > 64 => throw new InvalidOperationException(
+ $"Invalid parallel worker count ({requestedRunnerCount}) specified in verifier settings."),
+ 1 => new SequentialStepRunner(ServiceProvider),
+ _ => new AsyncStepRunner(requestedRunnerCount, ServiceProvider)
+ };
}
- protected override async Task RunCoreAsync(CancellationToken token)
- {
- var aggregatedVerifyProgressReporter = new AggregatedVerifyProgressReporter(_progressReporter, _verificationSteps);
+ protected override async Task PrepareCoreAsync(CancellationToken token)
+ {
+ _verifiers.Clear();
+
+ IStarWarsGameEngine gameEngine;
try
{
- Logger?.LogInformation("Running game verifiers...");
- _verifyRunner.Error += OnError;
- await _verifyRunner.RunAsync(token);
+ gameEngine = await _gameEngineService.InitializeAsync(
+ _verificationTarget.Engine,
+ _verificationTarget.Location,
+ _engineErrorReporter,
+ _engineInitializationReporter,
+ false,
+ CancellationToken.None).ConfigureAwait(false);
}
- finally
+ catch (Exception e)
{
- aggregatedVerifyProgressReporter.Dispose();
- _verifyRunner.Error -= OnError;
- Logger?.LogDebug("Game verifiers finished.");
+ _logger?.LogError(e, "Creating game engine failed: {Message}", e.Message);
+ throw;
}
- token.ThrowIfCancellationRequested();
-
- var failedSteps = _verifyRunner.ExecutedSteps.Where(p =>
- p.Error != null && !p.Error.IsExceptionType()).ToList();
+ AddStep(new GameEngineErrorCollector(_engineErrorReporter, gameEngine, _pipelineSettings.GameVerifySettings, ServiceProvider));
- if (failedSteps.Count != 0)
- throw new StepFailureException(failedSteps);
+ foreach (var gameVerificationStep in CreateVerificationSteps(gameEngine))
+ AddStep(gameVerificationStep);
+ }
+ protected override void OnExecuteStarted()
+ {
+ Logger?.LogInformation("Running game verifiers...");
+ _aggregatedVerifyProgressReporter = new AggregatedVerifyProgressReporter(_progressReporter, _verificationSteps);
+ _progressReporter.Report(0.0, $"Verifying {_verificationTarget.Name}...", VerifyProgress.ProgressType, default);
+ }
+
+ protected override void OnExecuteCompleted()
+ {
+ Logger?.LogInformation("Game verifiers finished.");
FilteredErrors = GetReportableErrors(_verifiers.SelectMany(s => s.VerifyErrors)).ToList();
+ _progressReporter.Report(1.0, $"Finished Verifying {_verificationTarget.Name}", VerifyProgress.ProgressType, default);
}
- protected override void OnError(object sender, StepRunnerErrorEventArgs e)
+ protected override void OnRunnerExecutionError(object sender, StepRunnerErrorEventArgs e)
{
if (FailFast && e.Exception is GameVerificationException v)
{
@@ -107,18 +115,13 @@ protected override void OnError(object sender, StepRunnerErrorEventArgs e)
if (v.Errors.All(error => _reportSettings.Baseline.Contains(error) || _reportSettings.Suppressions.Suppresses(error)))
return;
}
- base.OnError(sender, e);
- }
-
- private IEnumerable CreateVerificationSteps(IStarWarsGameEngine database)
- {
- return _pipelineSettings.VerifiersProvider.GetVerifiers(database, _pipelineSettings.GameVerifySettings, ServiceProvider);
+ base.OnRunnerExecutionError(sender, e);
}
private void AddStep(GameVerifier verifier)
{
var verificationStep = new GameVerifierPipelineStep(verifier, ServiceProvider);
- _verifyRunner.AddStep(verificationStep);
+ StepRunner.AddStep(verificationStep);
_verificationSteps.Add(verificationStep);
_verifiers.Add(verifier);
}
@@ -131,4 +134,16 @@ private IEnumerable GetReportableErrors(IEnumerable CreateVerificationSteps(IStarWarsGameEngine engine)
+ {
+ return _pipelineSettings.VerifiersProvider
+ .GetVerifiers(engine, _pipelineSettings.GameVerifySettings, ServiceProvider);
+ }
+
+ protected override void DisposeResources()
+ {
+ base.DisposeResources();
+ _aggregatedVerifyProgressReporter?.Dispose();
+ }
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Json/JsonBaselineParser.cs b/src/ModVerify/Reporting/Json/JsonBaselineParser.cs
index ef2f5d1..669ef53 100644
--- a/src/ModVerify/Reporting/Json/JsonBaselineParser.cs
+++ b/src/ModVerify/Reporting/Json/JsonBaselineParser.cs
@@ -1,11 +1,10 @@
using System;
using System.IO;
using System.Text.Json;
-using System.Text.Json.Nodes;
namespace AET.ModVerify.Reporting.Json;
-public static class JsonBaselineParser
+internal static class JsonBaselineParser
{
public static VerificationBaseline Parse(Stream dataStream)
{
@@ -13,8 +12,8 @@ public static VerificationBaseline Parse(Stream dataStream)
throw new ArgumentNullException(nameof(dataStream));
try
{
- var jsonNode = JsonNode.Parse(dataStream);
- var jsonBaseline = ParseCore(jsonNode);
+ var jsonNode = JsonDocument.Parse(dataStream);
+ var jsonBaseline = EvaluateAndDeserialize(jsonNode);
if (jsonBaseline is null)
throw new InvalidBaselineException($"Unable to parse input from stream to {nameof(VerificationBaseline)}. Unknown Error!");
@@ -27,12 +26,11 @@ public static VerificationBaseline Parse(Stream dataStream)
}
}
- private static JsonVerificationBaseline? ParseCore(JsonNode? jsonData)
+ private static JsonVerificationBaseline? EvaluateAndDeserialize(JsonDocument? json)
{
- if (jsonData is null)
+ if (json is null)
return null;
-
- JsonBaselineSchema.Evaluate(jsonData);
- return jsonData.Deserialize();
+ JsonBaselineSchema.Evaluate(json.RootElement);
+ return json.Deserialize();
}
}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Json/JsonBaselineSchema.cs b/src/ModVerify/Reporting/Json/JsonBaselineSchema.cs
index 7c8b02a..12e3705 100644
--- a/src/ModVerify/Reporting/Json/JsonBaselineSchema.cs
+++ b/src/ModVerify/Reporting/Json/JsonBaselineSchema.cs
@@ -3,8 +3,9 @@
using System.Diagnostics;
using System.Linq;
using System.Text;
-using System.Text.Json.Nodes;
+using System.Text.Json;
using Json.Schema;
+using Json.Schema.Keywords;
namespace AET.ModVerify.Reporting.Json;
@@ -12,18 +13,20 @@ public static class JsonBaselineSchema
{
private static readonly JsonSchema Schema;
private static readonly EvaluationOptions EvaluationOptions;
-
+ private static readonly BuildOptions BuildOptions;
+
static JsonBaselineSchema()
{
- var evalvOptions = new EvaluationOptions
+ BuildOptions = new BuildOptions
{
- EvaluateAs = SpecVersion.Draft202012,
- OutputFormat = OutputFormat.Hierarchical,
- AllowReferencesIntoUnknownKeywords = false
+ Dialect = Dialect.Draft202012
};
Schema = GetCurrentSchema();
- EvaluationOptions = evalvOptions;
+ EvaluationOptions = new EvaluationOptions
+ {
+ OutputFormat = OutputFormat.Hierarchical
+ };
}
///
@@ -31,11 +34,8 @@ static JsonBaselineSchema()
///
/// The JSON node to evaluate.
/// is not valid against the baseline JSON schema.
- /// is .
- public static void Evaluate(JsonNode json)
+ public static void Evaluate(JsonElement json)
{
- if (json == null)
- throw new ArgumentNullException(nameof(json));
var result = Schema.Evaluate(json, EvaluationOptions);
ThrowOnValidationError(result);
}
@@ -58,13 +58,17 @@ private static void ThrowOnValidationError(EvaluationResults result)
private static KeyValuePair? GetFirstError(EvaluationResults result)
{
- if (result.HasErrors)
- return result.Errors!.First();
- foreach (var child in result.Details)
+ if (result.Errors is not null)
+ return result.Errors.First();
+
+ if (result.Details is not null)
{
- var error = GetFirstError(child);
- if (error is not null)
- return error;
+ foreach (var child in result.Details)
+ {
+ var error = GetFirstError(child);
+ if (error is not null)
+ return error;
+ }
}
return null;
}
@@ -75,10 +79,12 @@ private static JsonSchema GetCurrentSchema()
.Assembly.GetManifestResourceStream($"AET.ModVerify.Resources.Schemas.{GetVersionedPath()}.baseline.json");
Debug.Assert(resourceStream is not null);
- var schema = JsonSchema.FromStream(resourceStream!).GetAwaiter().GetResult();
+ var json = JsonDocument.Parse(resourceStream!).RootElement;
+ var schema = JsonSchema.Build(json, BuildOptions);
+
- var id = schema.GetId();
- if (id is null || !UriContainsVersion(id, VerificationBaseline.LatestVersionString))
+ if (schema.Root.Keywords.FirstOrDefault(x => x.Handler is IdKeyword)?.Value is not Uri id
+ || !UriContainsVersion(id, VerificationBaseline.LatestVersionString))
throw new InvalidOperationException("Internal error: The embedded schema version does not match the expected baseline version!");
return schema;
diff --git a/src/ModVerify/Reporting/Json/JsonGameLocation.cs b/src/ModVerify/Reporting/Json/JsonGameLocation.cs
new file mode 100644
index 0000000..3f088f1
--- /dev/null
+++ b/src/ModVerify/Reporting/Json/JsonGameLocation.cs
@@ -0,0 +1,38 @@
+using System.Collections.Generic;
+using System.Linq;
+using System.Text.Json.Serialization;
+using PG.StarWarsGame.Engine;
+
+namespace AET.ModVerify.Reporting.Json;
+
+internal class JsonGameLocation
+{
+ [JsonPropertyName("modPaths")]
+ public IReadOnlyList ModPaths { get; }
+
+ [JsonPropertyName("gamePath")]
+ public string GamePath { get; }
+
+ [JsonPropertyName("fallbackPaths")]
+ public IReadOnlyList FallbackPaths { get; }
+
+ [JsonConstructor]
+ private JsonGameLocation(IReadOnlyList modPaths, string gamePath, IReadOnlyList fallbackPaths)
+ {
+ ModPaths = modPaths;
+ GamePath = gamePath;
+ FallbackPaths = fallbackPaths;
+ }
+
+ public JsonGameLocation(GameLocations location)
+ {
+ ModPaths = location.ModPaths.ToArray();
+ GamePath = location.GamePath;
+ FallbackPaths = location.FallbackPaths.ToArray();
+ }
+
+ public static GameLocations ToLocation(JsonGameLocation jsonLocation)
+ {
+ return new GameLocations(jsonLocation.ModPaths, jsonLocation.GamePath, jsonLocation.FallbackPaths);
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/Json/JsonVerificationBaseline.cs b/src/ModVerify/Reporting/Json/JsonVerificationBaseline.cs
index 4688c98..0d9a1b7 100644
--- a/src/ModVerify/Reporting/Json/JsonVerificationBaseline.cs
+++ b/src/ModVerify/Reporting/Json/JsonVerificationBaseline.cs
@@ -10,6 +10,10 @@ internal class JsonVerificationBaseline
[JsonPropertyName("version")]
public Version? Version { get; }
+ [JsonPropertyName("target")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public JsonVerificationTarget? Target { get; }
+
[JsonPropertyName("minSeverity")]
[JsonConverter(typeof(JsonStringEnumConverter))]
public VerificationSeverity MinimumSeverity { get; }
@@ -22,11 +26,17 @@ public JsonVerificationBaseline(VerificationBaseline baseline)
Errors = baseline.Select(x => new JsonVerificationError(x));
Version = baseline.Version;
MinimumSeverity = baseline.MinimumSeverity;
+ Target = baseline.Target is not null ? new JsonVerificationTarget(baseline.Target) : null;
}
[JsonConstructor]
- private JsonVerificationBaseline(Version version, VerificationSeverity minimumSeverity, IEnumerable errors)
+ private JsonVerificationBaseline(
+ JsonVerificationTarget target,
+ Version version,
+ VerificationSeverity minimumSeverity,
+ IEnumerable errors)
{
+ Target = target;
Errors = errors;
Version = version;
MinimumSeverity = minimumSeverity;
diff --git a/src/ModVerify/Reporting/Json/JsonVerificationTarget.cs b/src/ModVerify/Reporting/Json/JsonVerificationTarget.cs
new file mode 100644
index 0000000..451f7f7
--- /dev/null
+++ b/src/ModVerify/Reporting/Json/JsonVerificationTarget.cs
@@ -0,0 +1,51 @@
+using System.Text.Json.Serialization;
+using PG.StarWarsGame.Engine;
+
+namespace AET.ModVerify.Reporting.Json;
+
+internal class JsonVerificationTarget
+{
+ [JsonPropertyName("name")]
+ public string Name { get; }
+
+ [JsonPropertyName("engine")]
+ [JsonConverter(typeof(JsonStringEnumConverter))]
+ public GameEngineType Engine { get; }
+
+ [JsonPropertyName("version")]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
+ public string? Version{ get; }
+
+ [JsonPropertyName("location")]
+ public JsonGameLocation Location { get; }
+
+ [JsonConstructor]
+ private JsonVerificationTarget(string name, string? version, JsonGameLocation location, GameEngineType engine)
+ {
+ Name = name;
+ Version = version;
+ Engine = engine;
+ Location = location;
+ }
+
+ public JsonVerificationTarget(VerificationTarget target)
+ {
+ Name = target.Name;
+ Version = target.Version;
+ Engine = target.Engine;
+ Location = new JsonGameLocation(target.Location);
+ }
+
+ public static VerificationTarget? ToTarget(JsonVerificationTarget? jsonTarget)
+ {
+ if (jsonTarget is null)
+ return null;
+ return new VerificationTarget
+ {
+ Engine = jsonTarget.Engine,
+ Name = jsonTarget.Name,
+ Location = JsonGameLocation.ToLocation(jsonTarget.Location),
+ Version = jsonTarget.Version
+ };
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Reporting/VerificationBaseline.cs b/src/ModVerify/Reporting/VerificationBaseline.cs
index c37539b..ca8700d 100644
--- a/src/ModVerify/Reporting/VerificationBaseline.cs
+++ b/src/ModVerify/Reporting/VerificationBaseline.cs
@@ -3,21 +3,25 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
+using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using AET.ModVerify.Reporting.Json;
+using PG.StarWarsGame.Engine;
namespace AET.ModVerify.Reporting;
public sealed class VerificationBaseline : IReadOnlyCollection
{
- public static readonly Version LatestVersion = new(2, 0);
+ public static readonly Version LatestVersion = new(2, 1);
public static readonly string LatestVersionString = LatestVersion.ToString(2);
- public static readonly VerificationBaseline Empty = new(VerificationSeverity.Information, []);
+ public static readonly VerificationBaseline Empty = new(VerificationSeverity.Information, [], null);
private readonly HashSet _errors;
+ public VerificationTarget? Target { get; }
+
public Version? Version { get; }
public VerificationSeverity MinimumSeverity { get; }
@@ -30,13 +34,15 @@ internal VerificationBaseline(JsonVerificationBaseline baseline)
_errors = [..baseline.Errors.Select(x => new VerificationError(x))];
Version = baseline.Version;
MinimumSeverity = baseline.MinimumSeverity;
+ Target = JsonVerificationTarget.ToTarget(baseline.Target);
}
- public VerificationBaseline(VerificationSeverity minimumSeverity, IEnumerable errors)
+ public VerificationBaseline(VerificationSeverity minimumSeverity, IEnumerable errors, VerificationTarget? target)
{
_errors = [..errors];
Version = LatestVersion;
MinimumSeverity = minimumSeverity;
+ Target = target;
}
public bool Contains(VerificationError error)
@@ -77,6 +83,30 @@ IEnumerator IEnumerable.GetEnumerator()
public override string ToString()
{
- return $"Baseline [Version={Version}, MinSeverity={MinimumSeverity}, NumErrors={Count}]";
+ var sb = new StringBuilder($"Baseline [Version={Version}, MinSeverity={MinimumSeverity}, NumErrors={Count}");
+ if (Target is not null)
+ sb.Append($", Target={Target}");
+ sb.Append(']');
+ return sb.ToString();
+ }
+}
+
+public sealed class BaselineVerificationTarget
+{
+ public required GameEngineType Engine { get; init; }
+ public required string Name { get; init; }
+ public GameLocations? Location { get; init; }
+ public string? Version { get; init; }
+ public bool IsGame => Location.ModPaths.Count == 0;
+
+
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder($"[Name={Name};EngineType={Engine};");
+ if (!string.IsNullOrEmpty(Version)) sb.Append($"Version={Version};");
+ sb.Append($"Location={Location};");
+ sb.Append(']');
+ return sb.ToString();
}
}
\ No newline at end of file
diff --git a/src/ModVerify/Resources/Schemas/2.0/baseline.json b/src/ModVerify/Resources/Schemas/2.1/baseline.json
similarity index 57%
rename from src/ModVerify/Resources/Schemas/2.0/baseline.json
rename to src/ModVerify/Resources/Schemas/2.1/baseline.json
index 2520a58..ed5a014 100644
--- a/src/ModVerify/Resources/Schemas/2.0/baseline.json
+++ b/src/ModVerify/Resources/Schemas/2.1/baseline.json
@@ -1,9 +1,57 @@
{
- "$id": "https://AlamoEngine-Tools.github.io/schemas/mod-verify/2.0/baseline",
+ "$id": "https://AlamoEngine-Tools.github.io/schemas/mod-verify/2.1/baseline",
"$schema": "https://json-schema.org/draft/2020-12/schema",
"description": "Represents a baseline for AET ModVerify",
"type": "object",
"$defs": {
+ "location": {
+ "type": "object",
+ "properties": {
+ "modPaths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ },
+ "gamePath": {
+ "type": "string"
+ },
+ "fallbackPaths": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ }
+ }
+ },
+ "required": [
+ "modPaths",
+ "gamePath",
+ "fallbackPaths"
+ ],
+ "additionalProperties": false
+ },
+ "target": {
+ "type": "object",
+ "properties": {
+ "name": {
+ "type": "string"
+ },
+ "version": {
+ "type": "string"
+ },
+ "engine": {
+ "enum": [ "Eaw", "Foc" ]
+ },
+ "location": {
+ "$ref": "#/$defs/location"
+ }
+ },
+ "required": [
+ "name",
+ "engine"
+ ],
+ "additionalProperties": false
+ },
"severity": {
"enum": [ "Information", "Warning", "Error", "Critical" ]
},
@@ -48,7 +96,7 @@
},
"properties": {
"version": {
- "const": "2.0"
+ "const": "2.1"
},
"minSeverity": {
"$ref": "#/$defs/severity"
@@ -59,6 +107,9 @@
"$ref": "#/$defs/error"
},
"additionalItems": false
+ },
+ "target": {
+ "$ref": "#/$defs/target"
}
},
"required": [
diff --git a/src/ModVerify/VerificationTarget.cs b/src/ModVerify/VerificationTarget.cs
new file mode 100644
index 0000000..c0d5b97
--- /dev/null
+++ b/src/ModVerify/VerificationTarget.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Text;
+using PG.StarWarsGame.Engine;
+
+namespace AET.ModVerify;
+
+public sealed class VerificationTarget
+{
+ public required GameEngineType Engine { get; init; }
+
+ public required string Name
+ {
+ get;
+ init
+ {
+ if (string.IsNullOrEmpty(value))
+ throw new ArgumentNullException(nameof(value));
+ field = value;
+ }
+ }
+
+ public required GameLocations Location
+ {
+ get;
+ init => field = value ?? throw new ArgumentNullException(nameof(value));
+ }
+
+ public string? Version { get; init; }
+
+ public bool IsGame => Location.ModPaths.Count == 0;
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder($"[Name={Name};EngineType={Engine};");
+ if (!string.IsNullOrEmpty(Version))
+ sb.Append($"Version={Version};");
+ sb.Append($"Location={Location};");
+ sb.Append(']');
+ return sb.ToString();
+ }
+}
\ No newline at end of file
diff --git a/src/ModVerify/Verifiers/DuplicateNameFinder.cs b/src/ModVerify/Verifiers/DuplicateNameFinder.cs
index 23ab1b8..0b3b585 100644
--- a/src/ModVerify/Verifiers/DuplicateNameFinder.cs
+++ b/src/ModVerify/Verifiers/DuplicateNameFinder.cs
@@ -40,10 +40,10 @@ private void CheckForDuplicateCrcEntries(
string sourceName,
TSource source,
Func> crcSelector,
- Func> entrySelector,
+ Func> entrySelector,
Func entryToStringSelector,
- Func, IEnumerable> contextSelector,
- Func, string, string> errorMessageCreator)
+ Func, IEnumerable> contextSelector,
+ Func, string, string> errorMessageCreator)
{
foreach (var crc32 in crcSelector(source))
{
@@ -87,13 +87,13 @@ private void CheckXmlObjectsForDuplicates(string databaseName, IGameManager entries, string fileName)
+ private static string CreateDuplicateMtdErrorMessage(ImmutableFrugalList entries, string fileName)
{
var firstEntry = entries.First();
return $"MTD File '{fileName}' has duplicate definitions for CRC ({firstEntry}): {string.Join(",", entries.Select(x => x.FileName))}";
}
- private static string CreateDuplicateXmlErrorMessage(ReadOnlyFrugalList entries, string databaseName) where T : NamedXmlObject
+ private static string CreateDuplicateXmlErrorMessage(ImmutableFrugalList entries, string databaseName) where T : NamedXmlObject
{
var firstEntry = entries.First();
var message = $"{databaseName} '{firstEntry.Name}' ({firstEntry.Crc32}) has duplicate definitions: ";
diff --git a/src/ModVerify/Verifiers/GameVerifierBase.cs b/src/ModVerify/Verifiers/GameVerifierBase.cs
index 8c9d67d..02bacc4 100644
--- a/src/ModVerify/Verifiers/GameVerifierBase.cs
+++ b/src/ModVerify/Verifiers/GameVerifierBase.cs
@@ -15,10 +15,8 @@ namespace AET.ModVerify.Verifiers;
public abstract class GameVerifierBase : IGameVerifierInfo
{
public event EventHandler? Error;
-
public event EventHandler>? Progress;
- private readonly IStarWarsGameEngine _gameEngine;
private readonly ConcurrentDictionary _verifyErrors = new();
protected readonly IFileSystem FileSystem;
@@ -35,7 +33,7 @@ public abstract class GameVerifierBase : IGameVerifierInfo
protected IStarWarsGameEngine GameEngine { get; }
- protected IGameRepository Repository => _gameEngine.GameRepository;
+ protected IGameRepository Repository => GameEngine.GameRepository;
protected IReadOnlyList VerifierChain { get; }
@@ -49,7 +47,6 @@ protected GameVerifierBase(
throw new ArgumentNullException(nameof(serviceProvider));
FileSystem = serviceProvider.GetRequiredService();
Services = serviceProvider ?? throw new ArgumentNullException(nameof(serviceProvider));
- _gameEngine = gameEngine ?? throw new ArgumentNullException(nameof(gameEngine));
Parent = parent;
Settings = settings ?? throw new ArgumentNullException(nameof(settings));
GameEngine = gameEngine ?? throw new ArgumentNullException(nameof(gameEngine));
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
index 311c212..0b8687e 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/CommandBar/CommandBarGameManager.cs
@@ -1,6 +1,5 @@
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using PG.Commons.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.CommandBar.Components;
using PG.StarWarsGame.Engine.CommandBar.Xml;
@@ -18,6 +17,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
+using AnakinRaW.CommonUtilities.Collections;
namespace PG.StarWarsGame.Engine.CommandBar;
@@ -77,7 +77,7 @@ protected override async Task InitializeCoreAsync(CancellationToken token)
var contentParser = new XmlContainerContentParser(ServiceProvider, ErrorReporter);
contentParser.XmlParseError += OnParseError;
- var parsedCommandBarComponents = new ValueListDictionary();
+ var parsedCommandBarComponents = new FrugalValueListDictionary();
try
{
@@ -213,8 +213,8 @@ private void SetDefaultFont()
if (_defaultFont is null)
{
// TODO: From GameConstants
- string fontName = PGConstants.DefaultUnicodeFontName;
- int size = 11;
+ var fontName = PGConstants.DefaultUnicodeFontName;
+ var size = 11;
var font = fontManager.CreateFont(fontName, size, true, false, false, 1.0f);
if (font is null)
ErrorReporter.Assert(EngineAssert.FromNullOrEmpty([ToString()], $"Unable to create Default from name {fontName}"));
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/GameLocations.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/GameLocations.cs
index 3b77732..f57b605 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/GameLocations.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/GameLocations.cs
@@ -1,7 +1,8 @@
-using System;
+using AnakinRaW.CommonUtilities;
+using System;
using System.Collections.Generic;
using System.Linq;
-using AnakinRaW.CommonUtilities;
+using System.Text;
namespace PG.StarWarsGame.Engine;
@@ -27,13 +28,13 @@ public GameLocations(string modPath, string gamePath, string fallbackGamePath) :
ThrowHelper.ThrowIfNullOrEmpty(modPath);
}
- public GameLocations(IList modPaths, string gamePath, string fallbackGamePath) : this(modPaths,
- gamePath, [fallbackGamePath])
+ public GameLocations(IReadOnlyList modPaths, string gamePath, string fallbackGamePath)
+ : this(modPaths, gamePath, [fallbackGamePath])
{
ThrowHelper.ThrowIfNullOrEmpty(fallbackGamePath);
}
- public GameLocations(IList modPaths, string gamePath, IList fallbackPaths)
+ public GameLocations(IReadOnlyList modPaths, string gamePath, IReadOnlyList fallbackPaths)
{
if (modPaths == null)
throw new ArgumentNullException(nameof(modPaths));
@@ -48,4 +49,19 @@ public GameLocations(IList modPaths, string gamePath, IList fall
? ModPaths[0]
: GamePath;
}
+
+ public override string ToString()
+ {
+ var sb = new StringBuilder();
+
+ sb.AppendLine("GameLocation=[");
+ if (ModPaths.Count > 0)
+ sb.AppendLine($"Mods=[{string.Join(";", ModPaths)}];");
+ sb.AppendLine($"Game=[{GamePath}];");
+ if (FallbackPaths.Count > 0)
+ sb.AppendLine($"Fallbacks=[{string.Join(";", FallbackPaths)}];");
+ sb.AppendLine("]");
+
+ return sb.ToString();
+ }
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/GameManagerBase.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/GameManagerBase.cs
index 130fb50..607121d 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/GameManagerBase.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/GameManagerBase.cs
@@ -6,7 +6,6 @@
using AnakinRaW.CommonUtilities.Collections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using PG.Commons.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.ErrorReporting;
using PG.StarWarsGame.Engine.IO.Repositories;
@@ -16,13 +15,13 @@ namespace PG.StarWarsGame.Engine;
internal abstract class GameManagerBase(GameRepository repository, GameEngineErrorReporterWrapper errorReporter, IServiceProvider serviceProvider)
: GameManagerBase(repository, errorReporter, serviceProvider), IGameManager
{
- protected readonly ValueListDictionary NamedEntries = new();
+ protected readonly FrugalValueListDictionary NamedEntries = new();
public ICollection Entries => NamedEntries.Values;
public ICollection EntryKeys => NamedEntries.Keys;
- public ReadOnlyFrugalList GetEntries(Crc32 key)
+ public ImmutableFrugalList GetEntries(Crc32 key)
{
return NamedEntries.GetValues(key);
}
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/GuiDialog/Xml/XmlComponentTextureData.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/GuiDialog/Xml/XmlComponentTextureData.cs
index 2ed95ce..f102457 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/GuiDialog/Xml/XmlComponentTextureData.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/GuiDialog/Xml/XmlComponentTextureData.cs
@@ -1,14 +1,14 @@
using System;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.StarWarsGame.Engine.Xml;
using PG.StarWarsGame.Files.XML;
namespace PG.StarWarsGame.Engine.GuiDialog.Xml;
-public class XmlComponentTextureData(string componentId, IReadOnlyValueListDictionary textures, XmlLocationInfo location)
+public class XmlComponentTextureData(string componentId, IReadOnlyFrugalValueListDictionary textures, XmlLocationInfo location)
: XmlObject(location)
{
public string Component { get; } = componentId ?? throw new ArgumentNullException(componentId);
- public IReadOnlyValueListDictionary Textures { get; } = textures ?? throw new ArgumentNullException(nameof(textures));
+ public IReadOnlyFrugalValueListDictionary Textures { get; } = textures ?? throw new ArgumentNullException(nameof(textures));
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameEngineInitializationReporter.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameEngineInitializationReporter.cs
new file mode 100644
index 0000000..2ff43bd
--- /dev/null
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameEngineInitializationReporter.cs
@@ -0,0 +1,10 @@
+namespace PG.StarWarsGame.Engine;
+
+public interface IGameEngineInitializationReporter
+{
+ void ReportProgress(string message);
+
+ void ReportStarted();
+
+ void ReportFinished();
+}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameManager.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameManager.cs
index b9f60a7..750f00c 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameManager.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/IGameManager.cs
@@ -10,5 +10,5 @@ public interface IGameManager
ICollection EntryKeys { get; }
- ReadOnlyFrugalList GetEntries(Crc32 key);
+ ImmutableFrugalList GetEntries(Crc32 key);
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/IPetroglyphStarWarsGameEngineService.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/IPetroglyphStarWarsGameEngineService.cs
index 314ce06..80aaa61 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/IPetroglyphStarWarsGameEngineService.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/IPetroglyphStarWarsGameEngineService.cs
@@ -1,5 +1,4 @@
-using System;
-using System.Threading;
+using System.Threading;
using System.Threading.Tasks;
using PG.StarWarsGame.Engine.ErrorReporting;
@@ -11,7 +10,7 @@ public Task InitializeAsync(
GameEngineType engineType,
GameLocations gameLocations,
IGameEngineErrorReporter? errorReporter = null,
- IProgress? initProgress = null,
+ IGameEngineInitializationReporter? initReporter = null,
bool cancelOnInitializationError = false,
CancellationToken cancellationToken = default);
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/PG.StarWarsGame.Engine.csproj b/src/PetroglyphTools/PG.StarWarsGame.Engine/PG.StarWarsGame.Engine.csproj
index e54e6f0..43301f5 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/PG.StarWarsGame.Engine.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/PG.StarWarsGame.Engine.csproj
@@ -23,10 +23,10 @@
-
-
-
-
+
+
+
+
@@ -39,7 +39,4 @@
-
-
-
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/PetroglyphStarWarsGameEngineService.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/PetroglyphStarWarsGameEngineService.cs
index 8ce1a5a..02a8d9f 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/PetroglyphStarWarsGameEngineService.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/PetroglyphStarWarsGameEngineService.cs
@@ -27,7 +27,7 @@ public async Task InitializeAsync(
GameEngineType engineType,
GameLocations gameLocations,
IGameEngineErrorReporter? errorReporter = null,
- IProgress? progress = null,
+ IGameEngineInitializationReporter? initReporter = null,
bool cancelOnInitializationError = false,
CancellationToken cancellationToken = default)
@@ -39,7 +39,7 @@ public async Task InitializeAsync(
try
{
- return await InitializeEngine(engineType, gameLocations, errorListenerWrapper, progress, cts.Token)
+ return await InitializeEngineAsync(engineType, gameLocations, errorListenerWrapper, initReporter, cts.Token)
.ConfigureAwait(false);
}
finally
@@ -56,16 +56,17 @@ void OnInitializationError(object sender, InitializationError e)
}
}
- private async Task InitializeEngine(
+ private async Task InitializeEngineAsync(
GameEngineType engineType,
GameLocations gameLocations,
GameEngineErrorReporterWrapper errorReporter,
- IProgress? progress,
+ IGameEngineInitializationReporter? initReporter,
CancellationToken token)
{
try
{
_logger?.LogInformation("Initializing game engine for type '{GameEngineType}'.", engineType);
+ initReporter?.ReportStarted();
var repoFactory = _serviceProvider.GetRequiredService();
var repository = repoFactory.Create(engineType, gameLocations, errorReporter);
@@ -73,7 +74,7 @@ private async Task InitializeEngine(
var pgRender = new PGRender(repository, errorReporter, serviceProvider);
var gameConstants = new GameConstants.GameConstants(repository, errorReporter, serviceProvider);
- progress?.Report("Initializing GameConstants");
+ initReporter?.ReportProgress("Initializing GameConstants");
await gameConstants.InitializeAsync(token);
// AudioConstants
@@ -81,23 +82,23 @@ private async Task InitializeEngine(
// MousePointer
var fontManger = new FontManager(repository, errorReporter, serviceProvider);
- progress?.Report("Initializing FontManager");
+ initReporter?.ReportProgress("Initializing FontManager");
await fontManger.InitializeAsync(token);
var guiDialogs = new GuiDialogGameManager(repository, errorReporter, serviceProvider);
- progress?.Report("Initializing GUIDialogManager");
+ initReporter?.ReportProgress("Initializing GUIDialogManager");
await guiDialogs.InitializeAsync(token);
var sfxGameManager = new SfxEventGameManager(repository, errorReporter, serviceProvider);
- progress?.Report("Initializing SFXManager");
+ initReporter?.ReportProgress("Initializing SFXManager");
await sfxGameManager.InitializeAsync(token);
var commandBarManager = new CommandBarGameManager(repository, pgRender, gameConstants, fontManger, errorReporter, serviceProvider);
- progress?.Report("Initializing CommandBar");
+ initReporter?.ReportProgress("Initializing CommandBar");
await commandBarManager.InitializeAsync(token);
var gameObjetTypeManager = new GameObjectTypeGameManager(repository, errorReporter, serviceProvider);
- progress?.Report("Initializing GameObjectTypeManager");
+ initReporter?.ReportProgress("Initializing GameObjectTypeManager");
await gameObjetTypeManager.InitializeAsync(token);
token.ThrowIfCancellationRequested();
@@ -120,6 +121,7 @@ private async Task InitializeEngine(
}
finally
{
+ initReporter?.ReportFinished();
_logger?.LogDebug("Finished initializing game database.");
}
}
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Rendering/Animations/AnimationCollection.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Rendering/Animations/AnimationCollection.cs
index 03916fe..dfd43aa 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Rendering/Animations/AnimationCollection.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Rendering/Animations/AnimationCollection.cs
@@ -3,7 +3,6 @@
using System.Collections.Generic;
using AnakinRaW.CommonUtilities;
using AnakinRaW.CommonUtilities.Collections;
-using PG.Commons.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Files.ALO.Files.Animations;
@@ -13,10 +12,10 @@ public sealed class AnimationCollection : DisposableObject, IEnumerable _animations = new();
- private readonly ValueListDictionary _animationCrc = new();
+ private readonly FrugalValueListDictionary _animations = new();
+ private readonly FrugalValueListDictionary _animationCrc = new();
- public int Cout => _animations.Count;
+ public int Cout => _animations.ValueCount;
public Crc32 GetAnimationCrc(ModelAnimationType type, int subIndex)
{
@@ -28,12 +27,12 @@ public Crc32 GetAnimationCrc(ModelAnimationType type, int subIndex)
return checksumsForType[subIndex];
}
- public ReadOnlyFrugalList GetAnimations(ModelAnimationType type)
+ public ImmutableFrugalList GetAnimations(ModelAnimationType type)
{
return _animations.GetValues(type);
}
- public bool TryGetAnimations(ModelAnimationType type, out ReadOnlyFrugalList animations)
+ public bool TryGetAnimations(ModelAnimationType type, out ImmutableFrugalList animations)
{
return _animations.TryGetValues(type, out animations);
}
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/CommandBarComponentParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/CommandBarComponentParser.cs
index 1e20a8b..297b474 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/CommandBarComponentParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/CommandBarComponentParser.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.ObjectModel;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.CommandBar.Xml;
using PG.StarWarsGame.Engine.Xml.Tags;
@@ -12,7 +12,7 @@
namespace PG.StarWarsGame.Engine.Xml.Parsers.Data;
public sealed class CommandBarComponentParser(
- IReadOnlyValueListDictionary parsedElements,
+ IReadOnlyFrugalValueListDictionary parsedElements,
IServiceProvider serviceProvider,
IXmlParserErrorReporter? errorReporter = null)
: XmlObjectParser(parsedElements, serviceProvider, errorReporter)
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/GameObjectParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/GameObjectParser.cs
index 4f445a7..5cac3e2 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/GameObjectParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/GameObjectParser.cs
@@ -1,6 +1,6 @@
using System;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.GameObjects;
using PG.StarWarsGame.Files.XML;
@@ -26,7 +26,7 @@ public static class GameObjectXmlTags
}
public sealed class GameObjectParser(
- IReadOnlyValueListDictionary parsedElements,
+ IReadOnlyFrugalValueListDictionary parsedElements,
IServiceProvider serviceProvider,
IXmlParserErrorReporter? errorReporter = null)
: XmlObjectParser(parsedElements, serviceProvider, errorReporter)
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/SfxEventParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/SfxEventParser.cs
index 4e3a5cb..bc3439f 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/SfxEventParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/Data/SfxEventParser.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.ObjectModel;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.Audio.Sfx;
using PG.StarWarsGame.Engine.Xml.Tags;
@@ -12,7 +12,7 @@
namespace PG.StarWarsGame.Engine.Xml.Parsers.Data;
public sealed class SfxEventParser(
- IReadOnlyValueListDictionary parsedElements,
+ IReadOnlyFrugalValueListDictionary parsedElements,
IServiceProvider serviceProvider,
IXmlParserErrorReporter? errorReporter = null)
: XmlObjectParser(parsedElements, serviceProvider, errorReporter)
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/CommandBarComponentFileParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/CommandBarComponentFileParser.cs
index a32ff09..763d244 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/CommandBarComponentFileParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/CommandBarComponentFileParser.cs
@@ -1,6 +1,6 @@
using System;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.CommandBar.Xml;
using PG.StarWarsGame.Engine.Xml.Parsers.Data;
@@ -12,7 +12,7 @@ namespace PG.StarWarsGame.Engine.Xml.Parsers.File;
internal class CommandBarComponentFileParser(IServiceProvider serviceProvider, IXmlParserErrorReporter? errorReporter = null)
: PetroglyphXmlFileContainerParser(serviceProvider, errorReporter)
{
- protected override void Parse(XElement element, IValueListDictionary parsedElements, string fileName)
+ protected override void Parse(XElement element, IFrugalValueListDictionary parsedElements, string fileName)
{
var parser = new CommandBarComponentParser(parsedElements, ServiceProvider, ErrorReporter);
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GameObjectFileParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GameObjectFileParser.cs
index d2abfed..ffeafff 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GameObjectFileParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GameObjectFileParser.cs
@@ -1,6 +1,6 @@
using System;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.GameObjects;
using PG.StarWarsGame.Engine.Xml.Parsers.Data;
@@ -12,7 +12,7 @@ namespace PG.StarWarsGame.Engine.Xml.Parsers.File;
internal class GameObjectFileParser(IServiceProvider serviceProvider, IXmlParserErrorReporter? errorReporter = null)
: PetroglyphXmlFileContainerParser(serviceProvider, errorReporter)
{
- protected override void Parse(XElement element, IValueListDictionary parsedElements, string fileName)
+ protected override void Parse(XElement element, IFrugalValueListDictionary parsedElements, string fileName)
{
var parser = new GameObjectParser(parsedElements, ServiceProvider, ErrorReporter);
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GuiDialogParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GuiDialogParser.cs
index 7c23dd6..851aa9f 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GuiDialogParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/GuiDialogParser.cs
@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.StarWarsGame.Engine.GuiDialog.Xml;
using PG.StarWarsGame.Files.XML;
using PG.StarWarsGame.Files.XML.ErrorHandling;
@@ -49,7 +49,7 @@ private GuiDialogsXmlTextureData ParseTextures(XElement? element, string fileNam
private XmlComponentTextureData ParseTexture(XElement texture)
{
var componentId = GetTagName(texture);
- var textures = new ValueListDictionary();
+ var textures = new FrugalValueListDictionary();
foreach (var entry in texture.Elements())
textures.Add(entry.Name.ToString(), PetroglyphXmlStringParser.Instance.Parse(entry));
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/SfxEventFileParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/SfxEventFileParser.cs
index f40dd1a..841d805 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/SfxEventFileParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/File/SfxEventFileParser.cs
@@ -1,6 +1,6 @@
using System;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Engine.Audio.Sfx;
using PG.StarWarsGame.Engine.Xml.Parsers.Data;
@@ -12,7 +12,7 @@ namespace PG.StarWarsGame.Engine.Xml.Parsers.File;
internal class SfxEventFileParser(IServiceProvider serviceProvider, IXmlParserErrorReporter? errorReporter = null)
: PetroglyphXmlFileContainerParser(serviceProvider, errorReporter)
{
- protected override void Parse(XElement element, IValueListDictionary parsedElements, string fileName)
+ protected override void Parse(XElement element, IFrugalValueListDictionary parsedElements, string fileName)
{
var parser = new SfxEventParser(parsedElements, ServiceProvider, ErrorReporter);
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlContainerContentParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlContainerContentParser.cs
index 0c911e2..00f4f61 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlContainerContentParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlContainerContentParser.cs
@@ -1,9 +1,9 @@
using System;
using System.Linq;
using System.Xml;
+using AnakinRaW.CommonUtilities.Collections;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
-using PG.Commons.Collections;
using PG.Commons.Hashing;
using PG.Commons.Services;
using PG.StarWarsGame.Engine.IO;
@@ -34,7 +34,7 @@ public void ParseEntriesFromFileListXml(
string xmlFile,
IGameRepository gameRepository,
string lookupPath,
- ValueListDictionary entries,
+ FrugalValueListDictionary entries,
Action? onFileParseAction = null) where T : notnull
{
Logger.LogDebug("Parsing container data '{XmlFile}'", xmlFile);
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlObjectParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlObjectParser.cs
index fead02d..1565e9e 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlObjectParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Xml/Parsers/XmlObjectParser.cs
@@ -1,7 +1,7 @@
using System;
using System.Xml.Linq;
+using AnakinRaW.CommonUtilities.Collections;
using Microsoft.Extensions.DependencyInjection;
-using PG.Commons.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Files.XML.ErrorHandling;
using PG.StarWarsGame.Files.XML.Parsers;
@@ -9,7 +9,7 @@
namespace PG.StarWarsGame.Engine.Xml.Parsers;
public abstract class XmlObjectParser(
- IReadOnlyValueListDictionary parsedElements,
+ IReadOnlyFrugalValueListDictionary parsedElements,
IServiceProvider serviceProvider,
IXmlParserErrorReporter? errorReporter = null)
: XmlObjectParser(parsedElements, serviceProvider, errorReporter) where TObject : XmlObject
@@ -34,12 +34,12 @@ public readonly struct EmptyParseState
public abstract class XmlObjectParser(
- IReadOnlyValueListDictionary parsedElements,
+ IReadOnlyFrugalValueListDictionary parsedElements,
IServiceProvider serviceProvider,
IXmlParserErrorReporter? errorReporter = null)
: PetroglyphXmlElementParser(errorReporter) where TObject : XmlObject
{
- protected IReadOnlyValueListDictionary ParsedElements { get; } =
+ protected IReadOnlyFrugalValueListDictionary ParsedElements { get; } =
parsedElements ?? throw new ArgumentNullException(nameof(parsedElements));
protected ICrc32HashingService HashingService { get; } = serviceProvider.GetRequiredService();
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Files.ALO/PG.StarWarsGame.Files.ALO.csproj b/src/PetroglyphTools/PG.StarWarsGame.Files.ALO/PG.StarWarsGame.Files.ALO.csproj
index c653074..052190c 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Files.ALO/PG.StarWarsGame.Files.ALO.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Files.ALO/PG.StarWarsGame.Files.ALO.csproj
@@ -24,7 +24,4 @@
-
-
-
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Files.ChunkFiles/PG.StarWarsGame.Files.ChunkFiles.csproj b/src/PetroglyphTools/PG.StarWarsGame.Files.ChunkFiles/PG.StarWarsGame.Files.ChunkFiles.csproj
index 36221be..f49643c 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Files.ChunkFiles/PG.StarWarsGame.Files.ChunkFiles.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Files.ChunkFiles/PG.StarWarsGame.Files.ChunkFiles.csproj
@@ -17,9 +17,6 @@
preview
-
-
-
-
+
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/PG.StarWarsGame.Files.XML.csproj b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/PG.StarWarsGame.Files.XML.csproj
index fbb055c..75fecfd 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/PG.StarWarsGame.Files.XML.csproj
+++ b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/PG.StarWarsGame.Files.XML.csproj
@@ -18,8 +18,7 @@
preview
-
-
+
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/Base/IPetroglyphXmlFileContainerParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/Base/IPetroglyphXmlFileContainerParser.cs
index f42a9a9..cd21e00 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/Base/IPetroglyphXmlFileContainerParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/Base/IPetroglyphXmlFileContainerParser.cs
@@ -1,10 +1,10 @@
using System.IO;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
namespace PG.StarWarsGame.Files.XML.Parsers;
public interface IPetroglyphXmlFileContainerParser : IPetroglyphXmlParser where T : notnull
{
- void ParseFile(Stream xmlStream, IValueListDictionary parsedEntries);
+ void ParseFile(Stream xmlStream, IFrugalValueListDictionary parsedEntries);
}
\ No newline at end of file
diff --git a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/PetroglyphXmlFileContainerParser.cs b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/PetroglyphXmlFileContainerParser.cs
index 4e371e2..d2b862a 100644
--- a/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/PetroglyphXmlFileContainerParser.cs
+++ b/src/PetroglyphTools/PG.StarWarsGame.Files.XML/Parsers/PetroglyphXmlFileContainerParser.cs
@@ -1,7 +1,7 @@
using System;
using System.IO;
using System.Xml.Linq;
-using PG.Commons.Collections;
+using AnakinRaW.CommonUtilities.Collections;
using PG.Commons.Hashing;
using PG.StarWarsGame.Files.XML.ErrorHandling;
@@ -10,12 +10,12 @@ namespace PG.StarWarsGame.Files.XML.Parsers;
public abstract class PetroglyphXmlFileContainerParser(IServiceProvider serviceProvider, IXmlParserErrorReporter? listener = null)
: PetroglyphXmlFileParserBase(serviceProvider, listener), IPetroglyphXmlFileContainerParser where T : notnull
{
- public void ParseFile(Stream xmlStream, IValueListDictionary parsedEntries)
+ public void ParseFile(Stream xmlStream, IFrugalValueListDictionary parsedEntries)
{
var root = GetRootElement(xmlStream, out var fileName);
if (root is not null)
Parse(root, parsedEntries, fileName);
}
- protected abstract void Parse(XElement element, IValueListDictionary parsedElements, string fileName);
+ protected abstract void Parse(XElement element, IFrugalValueListDictionary parsedElements, string fileName);
}
\ No newline at end of file
diff --git a/test/ModVerify.CliApp.Test/CommonTestBase.cs b/test/ModVerify.CliApp.Test/CommonTestBase.cs
index 7d6dc18..8a93507 100644
--- a/test/ModVerify.CliApp.Test/CommonTestBase.cs
+++ b/test/ModVerify.CliApp.Test/CommonTestBase.cs
@@ -1,29 +1,22 @@
-using System;
-using System.IO.Abstractions;
+using AET.SteamAbstraction;
using AnakinRaW.CommonUtilities.Hashing;
+using AnakinRaW.CommonUtilities.Testing;
using Microsoft.Extensions.DependencyInjection;
using PG.Commons;
-using Testably.Abstractions.Testing;
+using PG.StarWarsGame.Infrastructure;
+using PG.StarWarsGame.Infrastructure.Clients.Steam;
namespace ModVerify.CliApp.Test;
-public abstract class CommonTestBase
+public abstract class CommonTestBase : TestBaseWithFileSystem
{
- protected readonly MockFileSystem FileSystem = new();
- protected readonly IServiceProvider ServiceProvider;
-
- protected CommonTestBase()
- {
- var sc = new ServiceCollection();
- sc.AddSingleton(sp => new HashingService(sp));
- sc.AddSingleton(FileSystem);
- PetroglyphCommons.ContributeServices(sc);
- // ReSharper disable once VirtualMemberCallInConstructor
- SetupServices(sc);
- ServiceProvider = sc.BuildServiceProvider();
- }
-
- protected virtual void SetupServices(ServiceCollection serviceCollection)
+ protected override void SetupServices(IServiceCollection serviceCollection)
{
+ base.SetupServices(serviceCollection);
+ serviceCollection.AddSingleton(sp => new HashingService(sp));
+ PetroglyphCommons.ContributeServices(serviceCollection);
+ PetroglyphGameInfrastructure.InitializeServices(serviceCollection);
+ SteamAbstractionLayer.InitializeServices(serviceCollection);
+ SteamPetroglyphStarWarsGameClients.InitializeServices(serviceCollection);
}
}
\ No newline at end of file
diff --git a/test/ModVerify.CliApp.Test/EmbeddedBaselineTest.cs b/test/ModVerify.CliApp.Test/EmbeddedBaselineTest.cs
index cde1dad..1747677 100644
--- a/test/ModVerify.CliApp.Test/EmbeddedBaselineTest.cs
+++ b/test/ModVerify.CliApp.Test/EmbeddedBaselineTest.cs
@@ -9,16 +9,18 @@
using System.IO.Abstractions;
using ModVerify.CliApp.Test.TestData;
using Testably.Abstractions;
+using Xunit;
namespace ModVerify.CliApp.Test;
public class BaselineSelectorTest
{
private static readonly IFileSystem FileSystem = new RealFileSystem();
+ private readonly IServiceProvider _serviceProvider;
private static readonly ModVerifyAppSettings TestSettings = new()
{
ReportSettings = new(),
- GameInstallationsSettings = new (),
+ VerificationTargetSettings = new (),
VerifyPipelineSettings = new()
{
GameVerifySettings = new GameVerifySettings(),
@@ -26,7 +28,6 @@ public class BaselineSelectorTest
}
};
- private readonly IServiceProvider _serviceProvider;
public BaselineSelectorTest()
{
@@ -42,6 +43,6 @@ public BaselineSelectorTest()
public void LoadEmbeddedBaseline(GameEngineType engineType)
{
// Ensure this operation does not crash, meaning the embedded baseline is at least compatible.
- new BaselineSelector(TestSettings, _serviceProvider).LoadEmbeddedBaseline(engineType);
+ BaselineSelector.LoadEmbeddedBaseline(engineType);
}
}
\ No newline at end of file
diff --git a/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj b/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
index 84d1bba..112201d 100644
--- a/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
+++ b/test/ModVerify.CliApp.Test/ModVerify.CliApp.Test.csproj
@@ -3,31 +3,36 @@
net10.0
$(TargetFrameworks);net481
- false
preview
+
+ false
+ true
+ Exe
+
+
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+
+
+
+
-
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
-
-
-
-
diff --git a/test/ModVerify.CliApp.Test/ModVerifyOptionsParserTest.cs b/test/ModVerify.CliApp.Test/ModVerifyOptionsParserTest.cs
index 294baf7..c5caf92 100644
--- a/test/ModVerify.CliApp.Test/ModVerifyOptionsParserTest.cs
+++ b/test/ModVerify.CliApp.Test/ModVerifyOptionsParserTest.cs
@@ -4,7 +4,11 @@
using System.IO.Abstractions;
using ModVerify.CliApp.Test.TestData;
using Testably.Abstractions;
+using Xunit;
+#if NETFRAMEWORK
using ModVerify.CliApp.Test.Utilities;
+#endif
+
namespace ModVerify.CliApp.Test;
diff --git a/test/ModVerify.CliApp.Test/TargetSelectors/AutomaticSelectorTest.cs b/test/ModVerify.CliApp.Test/TargetSelectors/AutomaticSelectorTest.cs
new file mode 100644
index 0000000..10156ac
--- /dev/null
+++ b/test/ModVerify.CliApp.Test/TargetSelectors/AutomaticSelectorTest.cs
@@ -0,0 +1,439 @@
+using AET.Modinfo.Model;
+using AET.Modinfo.Spec.Steam;
+using AET.ModVerify.App.GameFinder;
+using AET.ModVerify.App.Settings;
+using AET.ModVerify.App.TargetSelectors;
+using AET.ModVerify.App.Utilities;
+using AET.SteamAbstraction.Testing;
+using AnakinRaW.CommonUtilities.Registry;
+using Microsoft.Extensions.DependencyInjection;
+using PG.StarWarsGame.Engine;
+using PG.StarWarsGame.Infrastructure.Games;
+using PG.StarWarsGame.Infrastructure.Testing;
+using PG.StarWarsGame.Infrastructure.Testing.Installations;
+using PG.StarWarsGame.Infrastructure.Testing.Installations.Game;
+using System;
+using Xunit;
+
+namespace ModVerify.CliApp.Test.TargetSelectors;
+
+public class AutomaticSelectorTest : CommonTestBase
+{
+ private readonly AutomaticSelector _selector;
+ private readonly IRegistry _registry = new InMemoryRegistry(InMemoryRegistryCreationFlags.WindowsLike);
+
+ public AutomaticSelectorTest()
+ {
+ _selector = new AutomaticSelector(ServiceProvider);
+ }
+
+ protected override void SetupServices(IServiceCollection serviceCollection)
+ {
+ base.SetupServices(serviceCollection);
+ serviceCollection.AddSingleton(_registry);
+ }
+
+ [Fact]
+ public void Test_SelectTarget_GameNotInstalled()
+ {
+ var settings = new VerificationTargetSettings
+ {
+ TargetPath = "/test",
+ };
+ Assert.Throws(() => _selector.SelectTarget(settings));
+ }
+
+ [Fact]
+ public void Test_SelectTarget_WrongSettings()
+ {
+ var settings = new VerificationTargetSettings
+ {
+ TargetPath = "/test",
+ FallbackGamePath = "does/not/exist",
+ ModPaths = ["also/does/not/exist"],
+ GamePath = "not/found"
+ };
+ Assert.Throws(() => _selector.SelectTarget(settings));
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_FromGamePath(IGameIdentity identity)
+ {
+ TestSelectTarget(
+ identity,
+ i => i,
+ gi => new VerificationTargetSettings
+ {
+ TargetPath = gi.PlayableObject.Directory.FullName,
+ Engine = null
+ });
+ TestSelectTarget(
+ identity,
+ i => i,
+ gi => new VerificationTargetSettings
+ {
+ TargetPath = gi.PlayableObject.Directory.FullName,
+ Engine = gi.PlayableObject.Game.Type.ToEngineType()
+ });
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_FromGamePath_OppositeEngine(IGameIdentity identity)
+ {
+ if (identity.Platform is GamePlatform.SteamGold)
+ {
+ TestSelectTarget(identity,
+ i => i,
+ gi => new VerificationTargetSettings
+ {
+ TargetPath = gi.PlayableObject.Directory.FullName,
+ Engine = gi.PlayableObject.Game.Type.Opposite().ToEngineType(),
+ },
+ typeof(ArgumentException));
+ }
+ else
+ {
+ TestSelectTarget(identity,
+ i => i,
+ gi => new VerificationTargetSettings
+ {
+ TargetPath = gi.PlayableObject.Directory.FullName,
+ Engine = gi.PlayableObject.Game.Type.Opposite().ToEngineType(),
+ },
+ typeof(GameNotFoundException));
+ }
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_ModInModsDir(IGameIdentity identity)
+ {
+ TestSelectTarget(
+ identity,
+ gameInstallation => gameInstallation.InstallMod("MyMod", false),
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = null
+ });
+ TestSelectTarget(
+ identity,
+ gameInstallation => gameInstallation.InstallMod("MyMod", false),
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = ti.GameInstallation.Game.Type.ToEngineType()
+ });
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_ModInModsDir_WrongGameEngine_Throws(IGameIdentity identity)
+ {
+ var expectedExceptionType = identity.Platform == GamePlatform.SteamGold
+ ? typeof(ArgumentException)
+ : typeof(GameNotFoundException);
+
+ TestSelectTarget(
+ identity,
+ gameInstallation => gameInstallation.InstallMod("MyMod", false),
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = ti.GameInstallation.Game.Type.Opposite().ToEngineType()
+ }, expectedExceptionType);
+ }
+
+
+ [Theory]
+ [InlineData(GameType.Eaw)]
+ [InlineData(GameType.Foc)]
+ public void Test_SelectTarget_Workshops_UnknownModEngineType(GameType gameType)
+ {
+ var identity = new GameIdentity(gameType, GamePlatform.SteamGold);
+ TestSelectTarget(
+ identity,
+ gameInstallation => gameInstallation.InstallMod("MyMod", true),
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = ti.GameInstallation.Game.Type.ToEngineType()
+ });
+
+ TestSelectTarget(
+ identity,
+ gameInstallation => gameInstallation.InstallMod("MyMod", true),
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = null // Causes fallback to FoC
+ },
+ overrideAssertData: new OverrideAssertData { GameType = GameType.Foc });
+ }
+
+ [Theory]
+ [InlineData(GameType.Eaw)]
+ [InlineData(GameType.Foc)]
+ public void Test_SelectTarget_Workshops_UnspecifiedEngineIsCorrectEngineTyp_KnownModEngineType(GameType gameType)
+ {
+ var identity = new GameIdentity(gameType, GamePlatform.SteamGold);
+
+ var modinfo = new ModinfoData("MyMod")
+ {
+ SteamData = new SteamData("123456", "123456", SteamWorkshopVisibility.Public, "MyMod",
+ [gameType.ToString().ToUpper()])
+ };
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modInstallation = gameInstallation.InstallMod(modinfo, true);
+ modInstallation.InstallModinfoFile(modinfo);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = null
+ });
+ }
+
+ [Theory]
+ [InlineData(GameType.Eaw)]
+ [InlineData(GameType.Foc)]
+ public void Test_SelectTarget_Workshops_IncompatibleKnownModEngineType_Throws(GameType gameType)
+ {
+ var identity = new GameIdentity(gameType, GamePlatform.SteamGold);
+
+ var modinfo = new ModinfoData("MyMod")
+ {
+ SteamData = new SteamData("123456", "123456", SteamWorkshopVisibility.Public, "MyMod",
+ [gameType.ToString().ToUpper()])
+ };
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modInstallation = gameInstallation.InstallMod(modinfo, true);
+ modInstallation.InstallModinfoFile(modinfo);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = gameType.Opposite().ToEngineType()
+ },
+ typeof(ArgumentException));
+ }
+
+ [Theory]
+ [InlineData(GameType.Eaw)]
+ [InlineData(GameType.Foc)]
+ public void Test_SelectTarget_Workshops_MultipleKnownModEngineTypes(GameType gameType)
+ {
+ var identity = new GameIdentity(gameType, GamePlatform.SteamGold);
+
+ var modinfo = new ModinfoData("MyMod")
+ {
+ SteamData = new SteamData("123456", "123456", SteamWorkshopVisibility.Public, "MyMod",
+ [gameType.ToString().ToUpper(), gameType.Opposite().ToString().ToUpper()])
+ };
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modInstallation = gameInstallation.InstallMod(modinfo, true);
+ modInstallation.InstallModinfoFile(modinfo);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = gameType.ToEngineType()
+ });
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modInstallation = gameInstallation.InstallMod(modinfo, true);
+ modInstallation.InstallModinfoFile(modinfo);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = null // Causes fallback to FoC
+ },
+ overrideAssertData: new OverrideAssertData{GameType = GameType.Foc});
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_DetachedMod_NoEngineSpecified_Throws(IGameIdentity identity)
+ {
+ var exceptionType = identity.Platform is not GamePlatform.SteamGold
+ ? typeof(GameNotFoundException)
+ : typeof(ArgumentException);
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modinfo = new ModinfoData("DetachedMod");
+ var modPath = FileSystem.Directory.CreateDirectory("/detachedMod");
+ return gameInstallation.InstallMod(modinfo, modPath, false);
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = null // No Engine means we cannot proceed
+ },
+ expectedExceptionType: exceptionType);
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_DetachedMod(IGameIdentity identity)
+ {
+ // Currently, only Steam is supported for detached mods.
+ var exceptionType = identity.Platform is not GamePlatform.SteamGold
+ ? typeof(GameNotFoundException)
+ : null;
+
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modinfo = new ModinfoData("DetachedMod");
+ var modPath = FileSystem.Directory.CreateDirectory("/detachedMod");
+ return gameInstallation.InstallMod(modinfo, modPath, false);
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = identity.Type.ToEngineType()
+ },
+ expectedExceptionType: exceptionType);
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_AttachedMod_DoesNotExist(IGameIdentity identity)
+ {
+ // Currently, only Steam is supported for detached mods.
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modInstallation = gameInstallation.InstallMod("MyMod", GITestUtilities.GetRandomWorkshopFlag(identity));
+ modInstallation.Mod.Directory.Delete(true);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = identity.Type.ToEngineType()
+ },
+ typeof(TargetNotFoundException));
+ }
+
+ [Theory]
+ [MemberData(nameof(GITestUtilities.RealGameIdentities), MemberType = typeof(GITestUtilities))]
+ public void Test_SelectTarget_DetachedMod_DoesNotExist(IGameIdentity identity)
+ {
+ TestSelectTarget(
+ identity,
+ gameInstallation =>
+ {
+ var modinfo = new ModinfoData("DetachedMod");
+ var modPath = FileSystem.DirectoryInfo.New("/detachedMod");
+ var modInstallation = gameInstallation.InstallMod(modinfo, modPath, false);
+ modPath.Delete(true);
+ return modInstallation;
+ },
+ ti => new VerificationTargetSettings
+ {
+ TargetPath = ti.PlayableObject.Directory.FullName,
+ Engine = identity.Type.ToEngineType()
+ },
+ typeof(TargetNotFoundException));
+ }
+
+ private void TestSelectTarget(
+ IGameIdentity identity,
+ Func targetFactory,
+ Func settingsFactory,
+ Type? expectedExceptionType = null,
+ OverrideAssertData? overrideAssertData = null)
+ {
+ var (eaw, foc) = InstallGames(identity.Platform);
+ var gameInstallation = identity.Type switch
+ {
+ GameType.Eaw => eaw,
+ GameType.Foc => foc,
+ _ => throw new ArgumentOutOfRangeException()
+ };
+
+ var targetInstallation = targetFactory(gameInstallation);
+
+ var settings = settingsFactory(targetInstallation);
+
+ if (expectedExceptionType is not null)
+ {
+ Assert.Throws(expectedExceptionType, () => _selector.SelectTarget(settings));
+ return;
+ }
+
+ if (identity.Type == GameType.Foc && identity.Platform != GamePlatform.SteamGold)
+ Assert.Throws(() => _selector.SelectTarget(settings));
+ else
+ {
+ var result = _selector.SelectTarget(settings);
+ Assert.Equal(overrideAssertData?.GameType ?? identity.Type, result.Engine.FromEngineType());
+ Assert.Equal(targetInstallation.PlayableObject.GetType(), result.Target!.GetType());
+ Assert.Equal(targetInstallation.PlayableObject.Directory.FullName, result.Locations.TargetPath);
+
+ if (result.Engine == GameEngineType.Foc)
+ Assert.NotEmpty(result.Locations.FallbackPaths);
+ else
+ Assert.Empty(result.Locations.FallbackPaths);
+ }
+ }
+
+ private (ITestingGameInstallation eaw, ITestingGameInstallation foc) InstallGames(GamePlatform platform)
+ {
+ var eaw = GameInfrastructureTesting.Game(new GameIdentity(GameType.Eaw, platform), ServiceProvider);
+ var foc = GameInfrastructureTesting.Game(new GameIdentity(GameType.Foc, platform), ServiceProvider);
+
+ GameInfrastructureTesting.Registry(ServiceProvider).CreateInstalled(eaw.Game);
+ GameInfrastructureTesting.Registry(ServiceProvider).CreateInstalled(foc.Game);
+
+ eaw.InstallMod("OtherEawMod");
+ foc.InstallMod("OtherFocMod");
+
+ if (platform == GamePlatform.SteamGold)
+ InstallSteam();
+
+ return (eaw, foc);
+ }
+
+ private void InstallSteam()
+ {
+ var steam = SteamTesting.Steam(ServiceProvider);
+ steam.Install();
+ // Register Game to Steam
+ var lib = steam.InstallDefaultLibrary();
+ lib.InstallGame(32470, "Star Wars Empire at War", [32472]);
+ }
+
+ private class OverrideAssertData
+ {
+ public GameType? GameType { get; init; }
+ }
+}
\ No newline at end of file