From bae82ea3f89e0c5fd8c3b51025b30da87cc32a4b Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 13:53:08 +0200 Subject: [PATCH 1/6] reorganize cli handling --- src/ModVerify.CliApp/ExtensionMethods.cs | 17 +++ src/ModVerify.CliApp/GameFinderService.cs | 70 ++++----- src/ModVerify.CliApp/GameNotFoundException.cs | 5 + src/ModVerify.CliApp/ModOrGameSelector.cs | 141 ------------------ .../ModSelectors/AutomaticModSelector.cs | 134 +++++++++++++++++ .../ModSelectors/ConsoleModSelector.cs | 92 ++++++++++++ .../ModSelectors/IModSelector.cs | 10 ++ .../ModSelectors/ManualModSelector.cs | 27 ++++ .../ModSelectors/ModSelectorBase.cs | 73 +++++++++ .../ModSelectors/ModSelectorFactory.cs | 18 +++ .../ModSelectors/SettingsBasedModSelector.cs | 59 ++++++++ src/ModVerify.CliApp/ModVerifyApp.cs | 51 ++----- src/ModVerify.CliApp/ModVerifyOptions.cs | 43 ------ .../Options/GameInstallationsSettings.cs | 29 ++++ .../{ => Options}/ModVerifyAppSettings.cs | 10 +- .../Options/ModVerifyOptions.cs | 69 +++++++++ src/ModVerify.CliApp/Program.cs | 11 +- .../Properties/launchSettings.json | 5 + src/ModVerify.CliApp/SettingsBuilder.cs | 53 ++++++- .../VerifyGameInstallationData.cs | 28 ++++ src/ModVerify.CliApp/VerifyGameSetupData.cs | 13 -- .../Reporting/IVerificationReporter.cs | 3 +- .../Reporting/Reporters/ConsoleReporter.cs | 5 +- .../Reporting/Reporters/JSON/JsonReporter.cs | 8 +- .../Reporting/Reporters/ReporterBase.cs | 3 +- .../Reporters/Text/TextFileReporter.cs | 41 ++--- .../Reporting/VerificationReportBroker.cs | 8 +- src/ModVerify/VerifyGamePipeline.cs | 2 +- .../GameDatabaseCreationPipeline.cs | 6 +- 29 files changed, 715 insertions(+), 319 deletions(-) create mode 100644 src/ModVerify.CliApp/ExtensionMethods.cs create mode 100644 src/ModVerify.CliApp/GameNotFoundException.cs delete mode 100644 src/ModVerify.CliApp/ModOrGameSelector.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/IModSelector.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs create mode 100644 src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs delete mode 100644 src/ModVerify.CliApp/ModVerifyOptions.cs create mode 100644 src/ModVerify.CliApp/Options/GameInstallationsSettings.cs rename src/ModVerify.CliApp/{ => Options}/ModVerifyAppSettings.cs (58%) create mode 100644 src/ModVerify.CliApp/Options/ModVerifyOptions.cs create mode 100644 src/ModVerify.CliApp/VerifyGameInstallationData.cs delete mode 100644 src/ModVerify.CliApp/VerifyGameSetupData.cs diff --git a/src/ModVerify.CliApp/ExtensionMethods.cs b/src/ModVerify.CliApp/ExtensionMethods.cs new file mode 100644 index 0000000..a8580c1 --- /dev/null +++ b/src/ModVerify.CliApp/ExtensionMethods.cs @@ -0,0 +1,17 @@ +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure.Games; + +namespace ModVerify.CliApp.ModSelectors; + +internal static class ExtensionMethods +{ + public static GameEngineType ToEngineType(this GameType type) + { + return type == GameType.Foc ? GameEngineType.Foc : GameEngineType.Eaw; + } + + public static GameType FromEngineType(this GameEngineType type) + { + return type == GameEngineType.Foc ? GameType.Foc : GameType.EaW; + } +} \ No newline at end of file diff --git a/src/ModVerify.CliApp/GameFinderService.cs b/src/ModVerify.CliApp/GameFinderService.cs index 4b9f23a..12445f5 100644 --- a/src/ModVerify.CliApp/GameFinderService.cs +++ b/src/ModVerify.CliApp/GameFinderService.cs @@ -40,27 +40,28 @@ public GameFinderResult FindGames() return FindGames(detectors); } - public GameFinderResult FindGamesFromPath(string path) + public GameFinderResult FindGamesFromPathOrGlobal(string path) { - // There are three common situations: + // There are four common situations: // 1. path points to the actual game directory // 2. path points to a local mod in game/Mods/ModDir // 3. path points to a workshop mod + // 4. path points to a "detached mod" at a completely different location var givenDirectory = _fileSystem.DirectoryInfo.New(path); var possibleGameDir = givenDirectory.Parent?.Parent; - var possibleSteamAppsFolder = givenDirectory.Parent?.Parent?.Parent?.Parent?.Parent; var detectors = new List { + // Case 1 new DirectoryGameDetector(givenDirectory, _serviceProvider) }; + // Case 2 if (possibleGameDir is not null) detectors.Add(new DirectoryGameDetector(possibleGameDir, _serviceProvider)); - if (possibleSteamAppsFolder is not null && possibleSteamAppsFolder.Name == "steamapps" && uint.TryParse(givenDirectory.Name, out _)) - detectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider)); - + // Cases 3 & 4 + detectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider)); return FindGames(detectors); } @@ -80,32 +81,6 @@ private bool TryDetectGame(GameType gameType, IList detectors, ou return true; } - - private void SetupMods(IGame game) - { - var modFinder = _serviceProvider.GetRequiredService(); - var modRefs = modFinder.FindMods(game); - - var mods = new List(); - - foreach (var modReference in modRefs) - { - var mod = _modFactory.FromReference(game, modReference); - mods.AddRange(mod); - } - - foreach (var mod in mods) - game.AddMod(mod); - - // Mods need to be added to the game first, before resolving their dependencies. - foreach (var mod in mods) - { - var resolver = _serviceProvider.GetRequiredService(); - mod.ResolveDependencies(resolver, - new DependencyResolverOptions { CheckForCycle = true, ResolveCompleteChain = true }); - } - } - private GameFinderResult FindGames(IList detectors) { // FoC needs to be tried first @@ -113,11 +88,11 @@ private GameFinderResult FindGames(IList detectors) { _logger?.LogTrace("Unable to find FoC installation. Trying again with EaW..."); if (!TryDetectGame(GameType.EaW, detectors, out result)) - throw new GameException("Unable to find game installation: Wrong install path?"); + throw new GameNotFoundException("Unable to find game installation: Wrong install path?"); } if (result.GameLocation is null) - throw new GameException("Unable to find game installation: Wrong install path?"); + throw new GameNotFoundException("Unable to find game installation: Wrong install path?"); _logger?.LogTrace($"Found game installation: {result.GameIdentity} at {result.GameLocation.FullName}"); @@ -138,7 +113,7 @@ private GameFinderResult FindGames(IList detectors) throw new NotImplementedException("Searching fallback game for non-Steam games is currently is not yet implemented."); if (!TryDetectGame(GameType.EaW, fallbackDetectors, out var fallbackResult) || fallbackResult.GameLocation is null) - throw new GameException("Unable to find fallback game installation: Wrong install path?"); + throw new GameNotFoundException("Unable to find fallback game installation: Wrong install path?"); _logger?.LogTrace($"Found fallback game installation: {fallbackResult.GameIdentity} at {fallbackResult.GameLocation.FullName}"); @@ -149,4 +124,29 @@ private GameFinderResult FindGames(IList detectors) return new GameFinderResult(game, fallbackGame); } + + private void SetupMods(IGame game) + { + var modFinder = _serviceProvider.GetRequiredService(); + var modRefs = modFinder.FindMods(game); + + var mods = new List(); + + foreach (var modReference in modRefs) + { + var mod = _modFactory.FromReference(game, modReference); + mods.AddRange(mod); + } + + foreach (var mod in mods) + game.AddMod(mod); + + // Mods need to be added to the game first, before resolving their dependencies. + foreach (var mod in mods) + { + var resolver = _serviceProvider.GetRequiredService(); + mod.ResolveDependencies(resolver, + new DependencyResolverOptions { CheckForCycle = true, ResolveCompleteChain = true }); + } + } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/GameNotFoundException.cs b/src/ModVerify.CliApp/GameNotFoundException.cs new file mode 100644 index 0000000..9ee0502 --- /dev/null +++ b/src/ModVerify.CliApp/GameNotFoundException.cs @@ -0,0 +1,5 @@ +using PG.StarWarsGame.Infrastructure.Games; + +namespace ModVerify.CliApp; + +internal class GameNotFoundException(string message) : GameException(message); \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModOrGameSelector.cs b/src/ModVerify.CliApp/ModOrGameSelector.cs deleted file mode 100644 index 7659c38..0000000 --- a/src/ModVerify.CliApp/ModOrGameSelector.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO.Abstractions; -using EawModinfo.Spec; -using Microsoft.Extensions.DependencyInjection; -using PG.StarWarsGame.Infrastructure; -using PG.StarWarsGame.Infrastructure.Games; -using PG.StarWarsGame.Infrastructure.Mods; - -namespace ModVerify.CliApp; - -internal class ModOrGameSelector(IServiceProvider serviceProvider) -{ - private readonly GameFinderService _gameFinderService = new(serviceProvider); - private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService(); - - public ModSelectionResult SelectModOrGame(string? searchPath) - { - if (string.IsNullOrEmpty(searchPath)) - return SelectFromConsoleInput(); - return SelectFromPath(searchPath!); - } - - private ModSelectionResult SelectFromPath(string searchPath) - { - var fullSearchPath = _fileSystem.Path.GetFullPath(searchPath); - var gameResult = _gameFinderService.FindGamesFromPath(fullSearchPath); - - IPhysicalPlayableObject? gameOrMod = null; - - if (gameResult.Game.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase)) - gameOrMod = gameResult.Game; - else - { - foreach (var mod in gameResult.Game.Mods) - { - if (mod is IPhysicalMod physicalMod) - { - if (physicalMod.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase)) - { - gameOrMod = physicalMod; - break; - } - } - } - } - - if (gameOrMod is null) - throw new GameException($"Unable to a game or mod matching the path '{fullSearchPath}'."); - - return new ModSelectionResult - { - FallbackGame = gameResult.FallbackGame, - ModOrGame = gameOrMod - }; - } - - private ModSelectionResult SelectFromConsoleInput() - { - var gameResult = _gameFinderService.FindGames(); - - var list = new List(); - - var game = gameResult.Game; - list.Add(gameResult.Game); - - Console.WriteLine($"0: {game.Name}"); - - var counter = 1; - - var workshopMods = new HashSet(new ModEqualityComparer(false, false)); - - foreach (var mod in game.Mods) - { - var isSteam = mod.Type == ModType.Workshops; - if (isSteam) - { - workshopMods.Add(mod); - continue; - } - Console.WriteLine($"{counter++}:\t{mod.Name}"); - list.Add(mod); - } - - if (gameResult.FallbackGame is not null) - { - var fallbackGame = gameResult.FallbackGame; - list.Add(fallbackGame); - Console.WriteLine($"{counter++}: {fallbackGame.Name}"); - - foreach (var mod in fallbackGame.Mods) - { - var isSteam = mod.Type == ModType.Workshops; - if (isSteam) - { - workshopMods.Add(mod); - continue; - } - Console.WriteLine($"{counter++}:\t{mod.Name}"); - list.Add(mod); - } - } - - Console.WriteLine("Workshop Items:"); - foreach (var mod in workshopMods) - { - Console.WriteLine($"{counter++}:\t{mod.Name}"); - list.Add(mod); - } - - - IPlayableObject? selectedObject = null; - - do - { - Console.Write("Select a game or mod to verify: "); - var numberString = Console.ReadLine(); - - if (!int.TryParse(numberString, out var number)) - continue; - if (number < list.Count) - selectedObject = list[number]; - } while (selectedObject is null); - - if (selectedObject is not IPhysicalPlayableObject physicalPlayableObject) - throw new InvalidOperationException(); - - var coercedFallbackGame = gameResult.FallbackGame; - if (selectedObject.Equals(gameResult.FallbackGame)) - coercedFallbackGame = null; - else if (selectedObject.Game.Equals(gameResult.FallbackGame)) - coercedFallbackGame = null; - - - return new ModSelectionResult - { - ModOrGame = physicalPlayableObject, - FallbackGame = coercedFallbackGame - }; - } -} \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs new file mode 100644 index 0000000..e558c58 --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs @@ -0,0 +1,134 @@ +using System; +using System.Diagnostics; +using System.IO.Abstractions; +using EawModinfo.Model; +using EawModinfo.Spec; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using ModVerify.CliApp.Options; +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.Dependencies; + +namespace ModVerify.CliApp.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; + Debug.Assert(pathToVerify is not null); + + actualEngineType = settings.EngineType; + + GameFinderResult finderResult; + try + { + finderResult = GameFinderService.FindGamesFromPathOrGlobal(pathToVerify); + } + catch (GameNotFoundException) + { + Logger?.LogError($"Unable to find games based of the given location '{settings.GamePath}'. Consider specifying all paths manually."); + 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."); + + // 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 modFactory = ServiceProvider.GetRequiredService(); + mod = modFactory.FromReference(game, new ModReference(modPath, ModType.Default), true); + + game.AddMod(mod); + + var resolver = ServiceProvider.GetRequiredService(); + mod.ResolveDependencies(resolver, + new DependencyResolverOptions { CheckForCycle = true, ResolveCompleteChain = true }); + + 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/ConsoleModSelector.cs b/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs new file mode 100644 index 0000000..46bed7f --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs @@ -0,0 +1,92 @@ +using System; +using System.Collections.Generic; +using EawModinfo.Spec; +using ModVerify.CliApp.Options; +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure; +using PG.StarWarsGame.Infrastructure.Mods; + +namespace ModVerify.CliApp.ModSelectors; + +internal class ConsoleModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider) +{ + public override GameLocations? Select(GameInstallationsSettings settings, out IPhysicalPlayableObject? targetObject, + out GameEngineType? actualEngineType) + { + var gameResult = GameFinderService.FindGames(); + targetObject = SelectPlayableObject(gameResult); + actualEngineType = targetObject.Game.Type.ToEngineType(); + return GetLocations(targetObject, gameResult, settings.AdditionalFallbackPaths); + } + + private IPhysicalPlayableObject SelectPlayableObject(GameFinderResult finderResult) + { + var list = new List(); + + var game = finderResult.Game; + list.Add(finderResult.Game); + + Console.WriteLine($"0: {game.Name}"); + + var counter = 1; + + var workshopMods = new HashSet(new ModEqualityComparer(false, false)); + + foreach (var mod in game.Mods) + { + if (mod is not IPhysicalMod physicalMod) + continue; + + var isSteam = mod.Type == ModType.Workshops; + if (isSteam) + { + workshopMods.Add(physicalMod); + continue; + } + Console.WriteLine($"{counter++}:\t{mod.Name}"); + list.Add(physicalMod); + } + + if (finderResult.FallbackGame is not null) + { + var fallbackGame = finderResult.FallbackGame; + list.Add(fallbackGame); + Console.WriteLine($"{counter++}: {fallbackGame.Name}"); + + foreach (var mod in fallbackGame.Mods) + { + + if (mod is not IPhysicalMod physicalMod) + continue; + + var isSteam = mod.Type == ModType.Workshops; + if (isSteam) + { + workshopMods.Add(physicalMod); + continue; + } + + Console.WriteLine($"{counter++}:\t{mod.Name}"); + list.Add(physicalMod); + } + } + + Console.WriteLine("Workshop Items:"); + foreach (var mod in workshopMods) + { + Console.WriteLine($"{counter++}:\t{mod.Name}"); + list.Add(mod); + } + + while (true) + { + Console.Write("Select a game or mod: "); + var numberString = Console.ReadLine(); + + if (!int.TryParse(numberString, out var number)) + continue; + if (number < list.Count) + return list[number]; + } + } +} \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModSelectors/IModSelector.cs b/src/ModVerify.CliApp/ModSelectors/IModSelector.cs new file mode 100644 index 0000000..a713778 --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/IModSelector.cs @@ -0,0 +1,10 @@ +using ModVerify.CliApp.Options; +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure; + +namespace ModVerify.CliApp.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 new file mode 100644 index 0000000..2d8abaf --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs @@ -0,0 +1,27 @@ +using System; +using ModVerify.CliApp.Options; +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure; + +namespace ModVerify.CliApp.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 new file mode 100644 index 0000000..6a2b442 --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using ModVerify.CliApp.Options; +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure; +using PG.StarWarsGame.Infrastructure.Mods; +using PG.StarWarsGame.Infrastructure.Services.Dependencies; + +namespace ModVerify.CliApp.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) + .Select(x => x.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 new file mode 100644 index 0000000..2afad15 --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs @@ -0,0 +1,18 @@ +using System; +using ModVerify.CliApp.Options; + +namespace ModVerify.CliApp.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 new file mode 100644 index 0000000..01ce498 --- /dev/null +++ b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs @@ -0,0 +1,59 @@ +using System; +using System.IO.Abstractions; +using System.Linq; +using EawModinfo.Model; +using EawModinfo.Spec; +using Microsoft.Extensions.DependencyInjection; +using ModVerify.CliApp.Options; +using PG.StarWarsGame.Engine; +using PG.StarWarsGame.Infrastructure; +using PG.StarWarsGame.Infrastructure.Games; +using PG.StarWarsGame.Infrastructure.Services.Name; + +namespace ModVerify.CliApp.ModSelectors; + +internal class SettingsBasedModSelector(IServiceProvider serviceProvider) +{ + private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService(); + public VerifyGameInstallationData 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 VerifyGameInstallationData + { + EngineType = engineType.Value, + GameLocations = gameLocations, + Name = GetNameFromGameLocations(targetObject, gameLocations, engineType.Value) + }; + } + + private string GetNameFromGameLocations(IPlayableObject? targetObject, GameLocations gameLocations, GameEngineType engineType) + { + if (targetObject is not null) + return targetObject.Name; + + var mod = gameLocations.ModPaths.FirstOrDefault(); + if (mod is not null) + return GetNameFromMod(mod); + return GetNameFromGame(engineType); + } + + private string GetNameFromGame(GameEngineType type) + { + var nameResolver = serviceProvider.GetRequiredService(); + return nameResolver.ResolveName(new GameIdentity(type.FromEngineType(), GamePlatform.Undefined)); + } + + private string GetNameFromMod(string mod) + { + var nameResolver = serviceProvider.GetRequiredService(); + return nameResolver.ResolveName(new ModReference(_fileSystem.Path.GetFullPath(mod), ModType.Default)); + } +} \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModVerifyApp.cs b/src/ModVerify.CliApp/ModVerifyApp.cs index eb6f7bd..b6a8dda 100644 --- a/src/ModVerify.CliApp/ModVerifyApp.cs +++ b/src/ModVerify.CliApp/ModVerifyApp.cs @@ -2,15 +2,13 @@ using System.Collections.Generic; using System.IO; using System.IO.Abstractions; -using System.Linq; using System.Threading.Tasks; using AET.ModVerify; using AET.ModVerify.Reporting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using PG.StarWarsGame.Engine; -using PG.StarWarsGame.Infrastructure.Mods; -using PG.StarWarsGame.Infrastructure.Services.Dependencies; +using ModVerify.CliApp.ModSelectors; +using ModVerify.CliApp.Options; namespace ModVerify.CliApp; @@ -23,12 +21,15 @@ public async Task RunApplication() { var returnCode = 0; - var gameSetupData = CreateGameSetupData(settings, services); - var verifyPipeline = new ModVerifyPipeline(gameSetupData.EngineType, gameSetupData.GameLocations, settings.GameVerifySettigns, services); + var installData = new SettingsBasedModSelector(services).CreateInstallationDataFromSettings(settings.GameInstallationsSettings); + + _logger?.LogInformation($"Verify install data: {installData}"); + + var verifyPipeline = new ModVerifyPipeline(installData.EngineType, installData.GameLocations, settings.GameVerifySettings, services); try { - _logger?.LogInformation($"Verifying {gameSetupData.VerifyObject.Name}..."); + _logger?.LogInformation($"Verifying '{installData.Name}'..."); await verifyPipeline.RunAsync().ConfigureAwait(false); _logger?.LogInformation("Finished Verifying"); } @@ -45,7 +46,7 @@ public async Task RunApplication() private async Task WriteBaseline(IEnumerable errors, string baselineFile) { - var currentBaseline = settings.GameVerifySettigns.GlobalReportSettings.Baseline; + var currentBaseline = settings.GameVerifySettings.GlobalReportSettings.Baseline; var newBaseline = currentBaseline.MergeWith(errors); @@ -56,38 +57,4 @@ private async Task WriteBaseline(IEnumerable errors, string b using var fs = _fileSystem.FileStream.New(fullPath, FileMode.Create, FileAccess.Write, FileShare.None); await newBaseline.ToJsonAsync(fs); } - - private static VerifyGameSetupData CreateGameSetupData(ModVerifyAppSettings options, IServiceProvider services) - { - var selectionResult = new ModOrGameSelector(services).SelectModOrGame(options.PathToVerify); - - IList mods = Array.Empty(); - if (selectionResult.ModOrGame is IMod mod) - { - var traverser = services.GetRequiredService(); - mods = traverser.Traverse(mod) - .Select(x => x.Mod) - .OfType().Select(x => x.Directory.FullName) - .ToList(); - } - - var fallbackPaths = new List(); - if (selectionResult.FallbackGame is not null) - fallbackPaths.Add(selectionResult.FallbackGame.Directory.FullName); - - if (!string.IsNullOrEmpty(options.AdditionalFallbackPath)) - fallbackPaths.Add(options.AdditionalFallbackPath); - - var gameLocations = new GameLocations( - mods, - selectionResult.ModOrGame.Game.Directory.FullName, - fallbackPaths); - - return new VerifyGameSetupData - { - EngineType = GameEngineType.Foc, - GameLocations = gameLocations, - VerifyObject = selectionResult.ModOrGame, - }; - } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModVerifyOptions.cs b/src/ModVerify.CliApp/ModVerifyOptions.cs deleted file mode 100644 index 323b78d..0000000 --- a/src/ModVerify.CliApp/ModVerifyOptions.cs +++ /dev/null @@ -1,43 +0,0 @@ -using AET.ModVerify.Reporting; -using CommandLine; - -namespace ModVerify.CliApp; - -internal class ModVerifyOptions -{ - [Option('p', "path", Required = false, - HelpText = "The path to a mod directory to verify. If not path is specified, " + - "the app searches for game installations and asks the user to select a game or mod.")] - public string? Path { get; set; } - - [Option('o', "output", Required = false, HelpText = "directory where result files shall be stored to.")] - public string? Output { get; set; } - - [Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] - public bool Verbose { get; set; } - - [Option("baseline", Required = false, HelpText = "Path to a JSON baseline file.")] - public string? Baseline { get; set; } - - [Option("suppressions", Required = false, HelpText = "Path to a JSON suppression file.")] - public string? Suppressions { get; set; } - - [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.")] - public VerificationSeverity? MinimumFailureSeverity { get; set; } - - - [Option("failFast", Required = false, Default = false, - HelpText = "When set, the application will abort on the first failure. The option also recognized the 'MinimumFailureSeverity' setting.")] - public bool FailFast { get; set; } - - [Option("createBaseline", Required = false, - HelpText = "When a path is specified, the tools creates a new baseline file. " + - "An existing file will be overwritten. " + - "Previous baselines are merged into the new baseline.")] - public string? NewBaselineFile { get; set; } - - [Option("fallbackPath", Required = false, - HelpText = "Additional fallback path, which may contain assets that shall be included when doing the verification.")] - public string? AdditionalFallbackPath { get; set; } -} \ No newline at end of file diff --git a/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs b/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs new file mode 100644 index 0000000..9f2ad0f --- /dev/null +++ b/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; +using PG.StarWarsGame.Engine; + +namespace ModVerify.CliApp.Options; + +internal 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; } = Array.Empty(); + + public string? GamePath { get; init; } + + public string? FallbackGamePath { get; init; } + + public IList AdditionalFallbackPaths { get; init; } = Array.Empty(); + + public GameEngineType? EngineType { get; init; } +} \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModVerifyAppSettings.cs b/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs similarity index 58% rename from src/ModVerify.CliApp/ModVerifyAppSettings.cs rename to src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs index 3e7092c..8b5e1bb 100644 --- a/src/ModVerify.CliApp/ModVerifyAppSettings.cs +++ b/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs @@ -2,18 +2,16 @@ using AET.ModVerify.Settings; using System.Diagnostics.CodeAnalysis; -namespace ModVerify.CliApp; +namespace ModVerify.CliApp.Options; -public record ModVerifyAppSettings +internal record ModVerifyAppSettings { - public GameVerifySettings GameVerifySettigns { get; init; } + public required GameVerifySettings GameVerifySettings { get; init; } - public string? PathToVerify { get; init; } = null; + public required GameInstallationsSettings GameInstallationsSettings { get; init; } public string Output { get; init; } = Environment.CurrentDirectory; - public string? AdditionalFallbackPath { get; init; } = null; - [MemberNotNullWhen(true, nameof(NewBaselinePath))] public bool CreateNewBaseline => !string.IsNullOrEmpty(NewBaselinePath); diff --git a/src/ModVerify.CliApp/Options/ModVerifyOptions.cs b/src/ModVerify.CliApp/Options/ModVerifyOptions.cs new file mode 100644 index 0000000..de9bb3a --- /dev/null +++ b/src/ModVerify.CliApp/Options/ModVerifyOptions.cs @@ -0,0 +1,69 @@ +using System.Collections.Generic; +using AET.ModVerify.Reporting; +using CommandLine; +using PG.StarWarsGame.Engine; + +namespace ModVerify.CliApp.Options; + +internal class ModVerifyOptions +{ + [Option('o', "output", Required = false, HelpText = "directory where result files shall be stored to.")] + public string? Output { get; set; } + + [Option('v', "verbose", Required = false, HelpText = "Set output to verbose messages.")] + public bool Verbose { get; set; } + + [Option("baseline", Required = false, HelpText = "Path to a JSON baseline file.")] + public string? Baseline { get; set; } + + [Option("suppressions", Required = false, HelpText = "Path to a JSON suppression file.")] + public string? Suppressions { get; set; } + + [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.")] + public VerificationSeverity? MinimumFailureSeverity { get; set; } + + [Option("failFast", Required = false, Default = false, + HelpText = "When set, the application will abort on the first failure. The option also recognized the 'MinimumFailureSeverity' setting.")] + public bool FailFast { get; set; } + + [Option("createBaseline", Required = false, + HelpText = "When a path is specified, the tools creates a new baseline file. " + + "An existing file will be overwritten. Previous baselines are merged into the new baseline.")] + public string? NewBaselineFile { get; set; } + + + [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 submods or base games itself. " + + "The argument cannot be combined with any of --mods, --game or --fallbackGame")] + public string? AutoPath { get; set; } + + + [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. " + + "Leave empty, if you want to verify a game. If you want to use the interactive mode, leave this, --game and --fallbackGame empty.")] + public IList? ModPaths { get; set; } + + + [Option("game", SetName = "manualPaths", Required = false, Default = null, + HelpText = "The path of the base game. For FoC mods this points to the FoC installation, for EaW mods this points to the EaW installation. " + + "Leave empty, if you want to auto-detect games. If you want to use the interactive mode, leave this, --mods and --fallbackGame empty. " + + "If this argument is set, you also need to set --mods (including sub mods) and --fallbackGame manually.")] + public string? GamePath { get; set; } + + [Option("fallbackGame", SetName = "manualPaths", Required = false, Default = null, + HelpText = "The path of the fallback game. Usually this points to the EaW installation. This argument only recognized if --game is set.")] + public string? FallbackGamePath { get; set; } + + + [Option("type", Required = false, Default = null, + HelpText = "The game type of the mod that shall be verified. Leave 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; set; } + + + [Option("additionalFallbackPaths", Required = false, Separator = ';', + HelpText = "Additional fallback paths, which may contain assets that shall be included when doing the verification. Do not add EaW here. " + + "Multiple paths can be separated using the ';' (semicolon) character.")] + public IList? AdditionalFallbackPath { get; set; } +} \ No newline at end of file diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs index 1a99252..9c3b2bd 100644 --- a/src/ModVerify.CliApp/Program.cs +++ b/src/ModVerify.CliApp/Program.cs @@ -7,7 +7,6 @@ using AET.ModVerify.Reporting.Reporters.JSON; using AET.ModVerify.Reporting.Reporters.Text; using AET.SteamAbstraction; -using AnakinRaW.CommonUtilities.FileSystem; using AnakinRaW.CommonUtilities.Hashing; using AnakinRaW.CommonUtilities.Registry; using AnakinRaW.CommonUtilities.Registry.Windows; @@ -15,6 +14,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; +using ModVerify.CliApp.Options; using PG.Commons.Extensibility; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Files.ALO; @@ -63,6 +63,9 @@ await parseResult.WithNotParsedAsync(e => var coreServiceCollection = CreateCoreServices(verifyOptions.Verbose); var coreServices = coreServiceCollection.BuildServiceProvider(); var logger = coreServices.GetService()?.CreateLogger(typeof(Program)); + + logger?.LogDebug($"Raw command line: {Environment.CommandLine}"); + try { var settings = new SettingsBuilder(coreServices) @@ -76,8 +79,8 @@ await parseResult.WithNotParsedAsync(e => } catch (Exception e) { + Console.WriteLine($"Error: {e.Message}"); logger?.LogCritical(e, e.Message); - Console.WriteLine(e.Message); return e.HResult; } } @@ -126,13 +129,13 @@ private static void SetupReporting(IServiceCollection serviceCollection, ModVeri serviceCollection.RegisterJsonReporter(new JsonReporterSettings { OutputDirectory = settings.Output, - MinimumReportSeverity = settings.GameVerifySettigns.GlobalReportSettings.MinimumReportSeverity + MinimumReportSeverity = settings.GameVerifySettings.GlobalReportSettings.MinimumReportSeverity }); serviceCollection.RegisterTextFileReporter(new TextFileReporterSettings { OutputDirectory = settings.Output, - MinimumReportSeverity = settings.GameVerifySettigns.GlobalReportSettings.MinimumReportSeverity + MinimumReportSeverity = settings.GameVerifySettings.GlobalReportSettings.MinimumReportSeverity }); } diff --git a/src/ModVerify.CliApp/Properties/launchSettings.json b/src/ModVerify.CliApp/Properties/launchSettings.json index 7e4c931..51b4cdc 100644 --- a/src/ModVerify.CliApp/Properties/launchSettings.json +++ b/src/ModVerify.CliApp/Properties/launchSettings.json @@ -3,6 +3,11 @@ "Interactive": { "commandName": "Project", "commandLineArgs": "-o verifyResults --minFailSeverity Information --baseline focBaseline.json" + }, + + "FromModPath": { + "commandName": "Project", + "commandLineArgs": "-o verifyResults --baseline focBaseline.json --path C:/test --type Foc" } } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/SettingsBuilder.cs b/src/ModVerify.CliApp/SettingsBuilder.cs index 3821bb8..f40ce30 100644 --- a/src/ModVerify.CliApp/SettingsBuilder.cs +++ b/src/ModVerify.CliApp/SettingsBuilder.cs @@ -1,9 +1,11 @@ using System; +using System.Collections.Generic; using System.IO; using System.IO.Abstractions; using AET.ModVerify.Reporting; using AET.ModVerify.Settings; using Microsoft.Extensions.DependencyInjection; +using ModVerify.CliApp.Options; namespace ModVerify.CliApp; @@ -20,10 +22,9 @@ public ModVerifyAppSettings BuildSettings(ModVerifyOptions options) return new ModVerifyAppSettings { - GameVerifySettigns = BuildGameVerifySettings(options), - PathToVerify = options.Path, + GameVerifySettings = BuildGameVerifySettings(options), + GameInstallationsSettings = BuildInstallationSettings(options), Output = output, - AdditionalFallbackPath = options.AdditionalFallbackPath, NewBaselinePath = options.NewBaselineFile }; } @@ -73,4 +74,50 @@ private GlobalVerificationReportSettings BuilderGlobalReportSettings(ModVerifyOp MinimumReportSeverity = VerificationSeverity.Information, }; } + + private GameInstallationsSettings BuildInstallationSettings(ModVerifyOptions options) + { + var modPaths = new List(); + if (options.ModPaths is not null) + { + foreach (var mod in options.ModPaths) + { + if (!string.IsNullOrEmpty(mod)) + modPaths.Add(_fileSystem.Path.GetFullPath(mod)); + } + } + + var fallbackPaths = new List(); + if (options.AdditionalFallbackPath is not null) + { + foreach (var fallback in options.AdditionalFallbackPath) + { + if (!string.IsNullOrEmpty(fallback)) + fallbackPaths.Add(_fileSystem.Path.GetFullPath(fallback)); + } + } + + var gamePath = options.GamePath; + if (!string.IsNullOrEmpty(gamePath)) + gamePath = _fileSystem.Path.GetFullPath(gamePath); + + + string? fallbackGamePath = null; + 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); + + return new GameInstallationsSettings + { + AutoPath = autoPath, + ModPaths = modPaths, + GamePath = gamePath, + FallbackGamePath = fallbackGamePath, + AdditionalFallbackPaths = fallbackPaths, + EngineType = options.GameType + }; + } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/VerifyGameInstallationData.cs b/src/ModVerify.CliApp/VerifyGameInstallationData.cs new file mode 100644 index 0000000..8e157a5 --- /dev/null +++ b/src/ModVerify.CliApp/VerifyGameInstallationData.cs @@ -0,0 +1,28 @@ +using System.Text; +using PG.StarWarsGame.Engine; + +namespace ModVerify.CliApp; + +internal class VerifyGameInstallationData +{ + 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/VerifyGameSetupData.cs b/src/ModVerify.CliApp/VerifyGameSetupData.cs deleted file mode 100644 index 621e0c2..0000000 --- a/src/ModVerify.CliApp/VerifyGameSetupData.cs +++ /dev/null @@ -1,13 +0,0 @@ -using PG.StarWarsGame.Engine; -using PG.StarWarsGame.Infrastructure; - -namespace ModVerify.CliApp; - -internal class VerifyGameSetupData -{ - public required IPhysicalPlayableObject VerifyObject { get; init; } - - public required GameEngineType EngineType { get; init; } - - public required GameLocations GameLocations { get; init; } -} \ No newline at end of file diff --git a/src/ModVerify/Reporting/IVerificationReporter.cs b/src/ModVerify/Reporting/IVerificationReporter.cs index a1a9c48..8b8664e 100644 --- a/src/ModVerify/Reporting/IVerificationReporter.cs +++ b/src/ModVerify/Reporting/IVerificationReporter.cs @@ -1,8 +1,9 @@ using System.Collections.Generic; +using System.Threading.Tasks; namespace AET.ModVerify.Reporting; public interface IVerificationReporter { - public void Report(IReadOnlyCollection errors); + public Task ReportAsync(IReadOnlyCollection errors); } \ No newline at end of file diff --git a/src/ModVerify/Reporting/Reporters/ConsoleReporter.cs b/src/ModVerify/Reporting/Reporters/ConsoleReporter.cs index 9dd7f30..bda277f 100644 --- a/src/ModVerify/Reporting/Reporters/ConsoleReporter.cs +++ b/src/ModVerify/Reporting/Reporters/ConsoleReporter.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace AET.ModVerify.Reporting.Reporters; internal class ConsoleReporter(VerificationReportSettings settings, IServiceProvider serviceProvider) : ReporterBase(settings, serviceProvider) { - public override void Report(IReadOnlyCollection errors) + public override Task ReportAsync(IReadOnlyCollection errors) { var filteredErrors = FilteredErrors(errors).ToList(); @@ -22,5 +23,7 @@ public override void Report(IReadOnlyCollection errors) Console.WriteLine(error); Console.WriteLine(); + + return Task.CompletedTask; } } \ No newline at end of file diff --git a/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs b/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs index abbe5f0..731482a 100644 --- a/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs +++ b/src/ModVerify/Reporting/Reporters/JSON/JsonReporter.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text.Json; +using System.Threading.Tasks; using AET.ModVerify.Reporting.Json; namespace AET.ModVerify.Reporting.Reporters.JSON; @@ -11,10 +12,13 @@ internal class JsonReporter(JsonReporterSettings settings, IServiceProvider serv public const string FileName = "VerificationResult.json"; - public override void Report(IReadOnlyCollection errors) + public override async Task ReportAsync(IReadOnlyCollection errors) { var report = new JsonVerificationReport(errors.Select(x => new JsonVerificationError(x))); +#if NET || NETSTANDARD2_1 + await +#endif using var fs = CreateFile(FileName); - JsonSerializer.Serialize(fs, report, ModVerifyJsonSettings.JsonSettings); + await JsonSerializer.SerializeAsync(fs, report, ModVerifyJsonSettings.JsonSettings); } } \ No newline at end of file diff --git a/src/ModVerify/Reporting/Reporters/ReporterBase.cs b/src/ModVerify/Reporting/Reporters/ReporterBase.cs index d7945af..9360c0e 100644 --- a/src/ModVerify/Reporting/Reporters/ReporterBase.cs +++ b/src/ModVerify/Reporting/Reporters/ReporterBase.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; namespace AET.ModVerify.Reporting.Reporters; @@ -11,7 +12,7 @@ public abstract class ReporterBase(T settings, IServiceProvider serviceProvid protected T Settings { get; } = settings ?? throw new ArgumentNullException(nameof(settings)); - public abstract void Report(IReadOnlyCollection errors); + public abstract Task ReportAsync(IReadOnlyCollection errors); protected IEnumerable FilteredErrors(IReadOnlyCollection errors) { diff --git a/src/ModVerify/Reporting/Reporters/Text/TextFileReporter.cs b/src/ModVerify/Reporting/Reporters/Text/TextFileReporter.cs index 86ce6d4..9ff34dd 100644 --- a/src/ModVerify/Reporting/Reporters/Text/TextFileReporter.cs +++ b/src/ModVerify/Reporting/Reporters/Text/TextFileReporter.cs @@ -1,48 +1,51 @@ using System; using System.Collections.Generic; using System.IO; -using System.IO.Abstractions; using System.Linq; -using Microsoft.Extensions.DependencyInjection; +using System.Threading.Tasks; namespace AET.ModVerify.Reporting.Reporters.Text; internal class TextFileReporter(TextFileReporterSettings settings, IServiceProvider serviceProvider) : FileBasedReporter(settings, serviceProvider) { internal const string SingleReportFileName = "VerificationResult.txt"; - - private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService(); - - public override void Report(IReadOnlyCollection errors) + + public override async Task ReportAsync(IReadOnlyCollection errors) { if (Settings.SplitIntoFiles) - ReportByVerifier(errors); + await ReportByVerifier(errors); else - ReportWhole(errors); + await ReportWhole(errors); } - private void ReportWhole(IReadOnlyCollection errors) + private async Task ReportWhole(IReadOnlyCollection errors) { +#if NET || NETSTANDARD2_1 + await +#endif using var streamWriter = new StreamWriter(CreateFile(SingleReportFileName)); - - foreach (var error in errors.OrderBy(x => x.Id)) - WriteError(error, streamWriter); - + + foreach (var error in errors.OrderBy(x => x.Id)) + await WriteError(error, streamWriter); + } - private void ReportByVerifier(IReadOnlyCollection errors) + private async Task ReportByVerifier(IReadOnlyCollection errors) { var grouped = errors.GroupBy(x => x.Verifier); foreach (var group in grouped) - ReportToSingleFile(group); + await ReportToSingleFile(group); } - private void ReportToSingleFile(IGrouping group) + private async Task ReportToSingleFile(IGrouping group) { var fileName = $"{GetVerifierName(group.Key)}Results.txt"; +#if NET || NETSTANDARD2_1 + await +#endif using var streamWriter = new StreamWriter(CreateFile(fileName)); foreach (var error in group.OrderBy(x => x.Id)) - WriteError(error, streamWriter); + await WriteError(error, streamWriter); } private static string GetVerifierName(string verifierTypeName) @@ -66,8 +69,8 @@ private static string GetVerifierName(string verifierTypeName) return name.ToString(); } - private static void WriteError(VerificationError error, StreamWriter writer) + private static async Task WriteError(VerificationError error, StreamWriter writer) { - writer.WriteLine($"[{error.Id}] {error.Message}"); + await writer.WriteLineAsync($"[{error.Id}] {error.Message}"); } } \ No newline at end of file diff --git a/src/ModVerify/Reporting/VerificationReportBroker.cs b/src/ModVerify/Reporting/VerificationReportBroker.cs index 57e7a03..f9c3c68 100644 --- a/src/ModVerify/Reporting/VerificationReportBroker.cs +++ b/src/ModVerify/Reporting/VerificationReportBroker.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Threading.Tasks; using AET.ModVerify.Verifiers; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -12,20 +13,17 @@ internal class VerificationReportBroker(GlobalVerificationReportSettings reportS private readonly ILogger? _logger = serviceProvider.GetService()?.CreateLogger(typeof(VerificationReportBroker)); - public IReadOnlyCollection Report(IEnumerable steps) + public async Task> ReportAsync(IEnumerable steps) { var suppressions = new SuppressionList(reportSettings.Suppressions); - var errors = GetReportableErrors(steps, suppressions); - var reporters = serviceProvider.GetServices(); - foreach (var reporter in reporters) { try { - reporter.Report(errors); + await reporter.ReportAsync(errors); } catch (Exception e) { diff --git a/src/ModVerify/VerifyGamePipeline.cs b/src/ModVerify/VerifyGamePipeline.cs index 994253e..e546447 100644 --- a/src/ModVerify/VerifyGamePipeline.cs +++ b/src/ModVerify/VerifyGamePipeline.cs @@ -92,7 +92,7 @@ protected sealed override async Task RunCoreAsync(CancellationToken token) Logger?.LogInformation("Reporting Errors"); var reportBroker = new VerificationReportBroker(Settings.GlobalReportSettings, ServiceProvider); - var errors = reportBroker.Report(_verificationSteps); + var errors = await reportBroker.ReportAsync(_verificationSteps); Errors = errors; diff --git a/src/PetroglyphTools/PG.StarWarsGame.Engine/Database/Initialization/GameDatabaseCreationPipeline.cs b/src/PetroglyphTools/PG.StarWarsGame.Engine/Database/Initialization/GameDatabaseCreationPipeline.cs index f5aff84..05f6e21 100644 --- a/src/PetroglyphTools/PG.StarWarsGame.Engine/Database/Initialization/GameDatabaseCreationPipeline.cs +++ b/src/PetroglyphTools/PG.StarWarsGame.Engine/Database/Initialization/GameDatabaseCreationPipeline.cs @@ -100,7 +100,7 @@ protected override async Task RunCoreAsync(CancellationToken token) } finally { - Logger?.LogInformation("Finished parsing XML Files..."); + Logger?.LogInformation("Finished parsing XML Files"); _parseXmlRunner.Error -= OnError; } @@ -109,8 +109,10 @@ protected override async Task RunCoreAsync(CancellationToken token) token.ThrowIfCancellationRequested(); + Logger?.LogInformation("Initializing Language files..."); var installedLanguages = repository.InitializeInstalledSfxMegFiles(); - + Logger?.LogInformation("Finished initializing Language files"); + repository.Seal(); From 2202e572c0bc1556b86ad90d9f21681b514fd964 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 17:06:54 +0200 Subject: [PATCH 2/6] update deps --- src/ModVerify.CliApp/ExtensionMethods.cs | 4 ++-- src/ModVerify.CliApp/GameFinderService.cs | 13 +++++++------ .../ModSelectors/AutomaticModSelector.cs | 3 ++- .../ModSelectors/SettingsBasedModSelector.cs | 19 ++++++++++++------- src/ModVerify.CliApp/ModVerify.CliApp.csproj | 4 ++-- src/ModVerify.CliApp/Program.cs | 13 +++++++++++++ 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/ModVerify.CliApp/ExtensionMethods.cs b/src/ModVerify.CliApp/ExtensionMethods.cs index a8580c1..23ed016 100644 --- a/src/ModVerify.CliApp/ExtensionMethods.cs +++ b/src/ModVerify.CliApp/ExtensionMethods.cs @@ -1,7 +1,7 @@ using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure.Games; -namespace ModVerify.CliApp.ModSelectors; +namespace ModVerify.CliApp; internal static class ExtensionMethods { @@ -12,6 +12,6 @@ public static GameEngineType ToEngineType(this GameType type) public static GameType FromEngineType(this GameEngineType type) { - return type == GameEngineType.Foc ? GameType.Foc : GameType.EaW; + return type == GameEngineType.Foc ? GameType.Foc : GameType.Eaw; } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/GameFinderService.cs b/src/ModVerify.CliApp/GameFinderService.cs index 12445f5..0096222 100644 --- a/src/ModVerify.CliApp/GameFinderService.cs +++ b/src/ModVerify.CliApp/GameFinderService.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO.Abstractions; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; @@ -67,7 +68,7 @@ public GameFinderResult FindGamesFromPathOrGlobal(string path) private bool TryDetectGame(GameType gameType, IList detectors, out GameDetectionResult result) { - var gd = new CompositeGameDetector(detectors, _serviceProvider, true); + var gd = new CompositeGameDetector(detectors, _serviceProvider); result = gd.Detect(new GameDetectorOptions(gameType)); if (result.Error is not null) @@ -87,7 +88,7 @@ private GameFinderResult FindGames(IList detectors) if (!TryDetectGame(GameType.Foc, detectors, out var result)) { _logger?.LogTrace("Unable to find FoC installation. Trying again with EaW..."); - if (!TryDetectGame(GameType.EaW, detectors, out result)) + if (!TryDetectGame(GameType.Eaw, detectors, out result)) throw new GameNotFoundException("Unable to find game installation: Wrong install path?"); } @@ -96,7 +97,7 @@ private GameFinderResult FindGames(IList detectors) _logger?.LogTrace($"Found game installation: {result.GameIdentity} at {result.GameLocation.FullName}"); - var game = _gameFactory.CreateGame(result); + var game = _gameFactory.CreateGame(result, CultureInfo.InvariantCulture); SetupMods(game); @@ -112,12 +113,12 @@ private GameFinderResult FindGames(IList detectors) else throw new NotImplementedException("Searching fallback game for non-Steam games is currently is not yet implemented."); - if (!TryDetectGame(GameType.EaW, fallbackDetectors, out var fallbackResult) || fallbackResult.GameLocation is null) + 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?.LogTrace($"Found fallback game installation: {fallbackResult.GameIdentity} at {fallbackResult.GameLocation.FullName}"); - fallbackGame = _gameFactory.CreateGame(fallbackResult); + fallbackGame = _gameFactory.CreateGame(fallbackResult, CultureInfo.InvariantCulture); SetupMods(fallbackGame); } @@ -134,7 +135,7 @@ private void SetupMods(IGame game) foreach (var modReference in modRefs) { - var mod = _modFactory.FromReference(game, modReference); + var mod = _modFactory.FromReference(game, modReference, CultureInfo.InvariantCulture); mods.AddRange(mod); } diff --git a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs index e558c58..b8369dc 100644 --- a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs @@ -1,5 +1,6 @@ using System; using System.Diagnostics; +using System.Globalization; using System.IO.Abstractions; using EawModinfo.Model; using EawModinfo.Spec; @@ -99,7 +100,7 @@ private GameLocations GetDetachedModLocations(string modPath, GameFinderResult g throw new GameNotFoundException($"Unable to find game of type '{settings.EngineType}'"); var modFactory = ServiceProvider.GetRequiredService(); - mod = modFactory.FromReference(game, new ModReference(modPath, ModType.Default), true); + mod = modFactory.FromReference(game, new ModReference(modPath, ModType.Default), true, CultureInfo.InvariantCulture); game.AddMod(mod); diff --git a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs index 01ce498..684423a 100644 --- a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs @@ -1,4 +1,5 @@ using System; +using System.Globalization; using System.IO.Abstractions; using System.Linq; using EawModinfo.Model; @@ -40,20 +41,24 @@ private string GetNameFromGameLocations(IPlayableObject? targetObject, GameLocat return targetObject.Name; var mod = gameLocations.ModPaths.FirstOrDefault(); - if (mod is not null) - return GetNameFromMod(mod); - return GetNameFromGame(engineType); + + var name = mod is not null ? GetNameFromMod(mod) : GetNameFromGame(engineType); + + if (string.IsNullOrEmpty(name)) + throw new InvalidOperationException("Mod or game name cannot be null or empty."); + + return name; } - private string GetNameFromGame(GameEngineType type) + private string? GetNameFromGame(GameEngineType type) { var nameResolver = serviceProvider.GetRequiredService(); - return nameResolver.ResolveName(new GameIdentity(type.FromEngineType(), GamePlatform.Undefined)); + return nameResolver.ResolveName(new GameIdentity(type.FromEngineType(), GamePlatform.Undefined), CultureInfo.InvariantCulture); } - private string GetNameFromMod(string mod) + private string? GetNameFromMod(string mod) { var nameResolver = serviceProvider.GetRequiredService(); - return nameResolver.ResolveName(new ModReference(_fileSystem.Path.GetFullPath(mod), ModType.Default)); + return nameResolver.ResolveName(new ModReference(_fileSystem.Path.GetFullPath(mod), ModType.Default), CultureInfo.InvariantCulture); } } \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj index 22a7164..e1cf550 100644 --- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj +++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj @@ -23,8 +23,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs index 9c3b2bd..d7e1b89 100644 --- a/src/ModVerify.CliApp/Program.cs +++ b/src/ModVerify.CliApp/Program.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using System.IO.Abstractions; using System.Runtime.CompilerServices; using System.Threading.Tasks; @@ -23,6 +24,8 @@ using PG.StarWarsGame.Files.XML; using PG.StarWarsGame.Infrastructure; using PG.StarWarsGame.Infrastructure.Clients; +using PG.StarWarsGame.Infrastructure.Services.Detection; +using PG.StarWarsGame.Infrastructure.Services.Name; using Serilog; using Serilog.Events; using Serilog.Filters; @@ -118,6 +121,16 @@ private static IServiceProvider CreateAppServices(IServiceCollection serviceColl ModVerifyServiceContribution.ContributeServices(serviceCollection); SetupReporting(serviceCollection, settings); + + serviceCollection.AddSingleton(sp => new CompositeModNameResolver(sp, s => + new List + { + new OfflineWorkshopNameResolver(s), + new OnlineWorkshopNameResolver(s), + new DirectoryModNameResolver(s) + })); + + serviceCollection.AddSingleton(sp => new OfflineModGameTypeResolver(sp)); return serviceCollection.BuildServiceProvider(); } From 3911575f600321974b6c36d325f941319528f2f6 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 17:07:17 +0200 Subject: [PATCH 3/6] update subs --- PetroglyphTools | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PetroglyphTools b/PetroglyphTools index 3efe081..1be8d39 160000 --- a/PetroglyphTools +++ b/PetroglyphTools @@ -1 +1 @@ -Subproject commit 3efe081031d1ab331c5af917be07454a943a2d4c +Subproject commit 1be8d395153c5a6a4babddbe62b07ea96cb95638 From 7e4d29cf4f81f4d33429d95a33ce98494313b6ca Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 17:11:03 +0200 Subject: [PATCH 4/6] update sub --- PetroglyphTools | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PetroglyphTools b/PetroglyphTools index 1be8d39..0347671 160000 --- a/PetroglyphTools +++ b/PetroglyphTools @@ -1 +1 @@ -Subproject commit 1be8d395153c5a6a4babddbe62b07ea96cb95638 +Subproject commit 0347671ec7c89d2a79b167e2110df3cd495f71aa From 596a01c1512b6b48e744a4a7f18227ed4be84f12 Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 18:05:39 +0200 Subject: [PATCH 5/6] cleanup --- .github/workflows/release.yml | 2 -- README.md | 2 +- src/ModVerify.CliApp/ExtensionMethods.cs | 2 +- .../{ => GameFinder}/GameFinderResult.cs | 2 +- .../{ => GameFinder}/GameFinderService.cs | 2 +- src/ModVerify.CliApp/GameNotFoundException.cs | 2 +- src/ModVerify.CliApp/ModSelectionResult.cs | 10 ---------- .../ModSelectors/AutomaticModSelector.cs | 5 +++-- .../ModSelectors/ConsoleModSelector.cs | 5 +++-- src/ModVerify.CliApp/ModSelectors/IModSelector.cs | 4 ++-- src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs | 4 ++-- src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs | 5 +++-- .../ModSelectors/ModSelectorFactory.cs | 4 ++-- .../ModSelectors/SettingsBasedModSelector.cs | 4 ++-- src/ModVerify.CliApp/ModVerify.CliApp.csproj | 2 ++ src/ModVerify.CliApp/ModVerifyApp.cs | 6 +++--- src/ModVerify.CliApp/ModVerifyPipeline.cs | 2 +- .../Options/GameInstallationsSettings.cs | 2 +- src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs | 4 ++-- src/ModVerify.CliApp/Options/ModVerifyOptions.cs | 2 +- src/ModVerify.CliApp/Program.cs | 4 ++-- src/ModVerify.CliApp/SettingsBuilder.cs | 4 ++-- src/ModVerify.CliApp/VerifyGameInstallationData.cs | 2 +- src/ModVerify/ModVerify.csproj | 1 + 24 files changed, 38 insertions(+), 44 deletions(-) rename src/ModVerify.CliApp/{ => GameFinder}/GameFinderResult.cs (74%) rename src/ModVerify.CliApp/{ => GameFinder}/GameFinderService.cs (99%) delete mode 100644 src/ModVerify.CliApp/ModSelectionResult.cs diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1c7a7be..31c58a8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -55,8 +55,6 @@ jobs: # Change into the artifacts directory to avoid including the directory itself in the zip archive working-directory: ./releases/net8.0 run: zip -r ../ModVerify-Net8.zip . - - name: Rename .NET Framework executable - run: mv ./releases/net48/ModVerify.CliApp.exe ./releases/net48/ModVerify.exe - uses: dotnet/nbgv@v0.4.2 id: nbgv - name: Create GitHub release diff --git a/README.md b/README.md index 3555a77..9ef3e13 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ A `.JSON` file lists all found issues. Into seperate `.txt` files the same error You can also run the tool with command line arguments to adjust the tool to your needs. -To see all available options, open the command line and type: +To see all available options, especially if you have custom folder setups, open the command line and type: ```bash ModVerify.exe --help diff --git a/src/ModVerify.CliApp/ExtensionMethods.cs b/src/ModVerify.CliApp/ExtensionMethods.cs index 23ed016..b7e20c8 100644 --- a/src/ModVerify.CliApp/ExtensionMethods.cs +++ b/src/ModVerify.CliApp/ExtensionMethods.cs @@ -1,7 +1,7 @@ using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure.Games; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal static class ExtensionMethods { diff --git a/src/ModVerify.CliApp/GameFinderResult.cs b/src/ModVerify.CliApp/GameFinder/GameFinderResult.cs similarity index 74% rename from src/ModVerify.CliApp/GameFinderResult.cs rename to src/ModVerify.CliApp/GameFinder/GameFinderResult.cs index 5d6cc94..3135955 100644 --- a/src/ModVerify.CliApp/GameFinderResult.cs +++ b/src/ModVerify.CliApp/GameFinder/GameFinderResult.cs @@ -1,5 +1,5 @@ using PG.StarWarsGame.Infrastructure.Games; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool.GameFinder; internal record GameFinderResult(IGame Game, IGame? FallbackGame); \ No newline at end of file diff --git a/src/ModVerify.CliApp/GameFinderService.cs b/src/ModVerify.CliApp/GameFinder/GameFinderService.cs similarity index 99% rename from src/ModVerify.CliApp/GameFinderService.cs rename to src/ModVerify.CliApp/GameFinder/GameFinderService.cs index 0096222..fa21e3b 100644 --- a/src/ModVerify.CliApp/GameFinderService.cs +++ b/src/ModVerify.CliApp/GameFinder/GameFinderService.cs @@ -11,7 +11,7 @@ using PG.StarWarsGame.Infrastructure.Services.Dependencies; using PG.StarWarsGame.Infrastructure.Services.Detection; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool.GameFinder; internal class GameFinderService { diff --git a/src/ModVerify.CliApp/GameNotFoundException.cs b/src/ModVerify.CliApp/GameNotFoundException.cs index 9ee0502..21cdc81 100644 --- a/src/ModVerify.CliApp/GameNotFoundException.cs +++ b/src/ModVerify.CliApp/GameNotFoundException.cs @@ -1,5 +1,5 @@ using PG.StarWarsGame.Infrastructure.Games; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class GameNotFoundException(string message) : GameException(message); \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModSelectionResult.cs b/src/ModVerify.CliApp/ModSelectionResult.cs deleted file mode 100644 index dee1c45..0000000 --- a/src/ModVerify.CliApp/ModSelectionResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using PG.StarWarsGame.Infrastructure; -using PG.StarWarsGame.Infrastructure.Games; - -namespace ModVerify.CliApp; - -internal record ModSelectionResult -{ - public IPhysicalPlayableObject ModOrGame { get; init; } - public IGame? FallbackGame { get; init; } -} \ No newline at end of file diff --git a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs index b8369dc..1d2a85f 100644 --- a/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs @@ -2,11 +2,12 @@ using System.Diagnostics; using System.Globalization; using System.IO.Abstractions; +using AET.ModVerifyTool.GameFinder; +using AET.ModVerifyTool.Options; using EawModinfo.Model; using EawModinfo.Spec; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using ModVerify.CliApp.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; using PG.StarWarsGame.Infrastructure.Games; @@ -14,7 +15,7 @@ using PG.StarWarsGame.Infrastructure.Services; using PG.StarWarsGame.Infrastructure.Services.Dependencies; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal class AutomaticModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider) { diff --git a/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs b/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs index 46bed7f..c218305 100644 --- a/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; +using AET.ModVerifyTool.GameFinder; +using AET.ModVerifyTool.Options; using EawModinfo.Spec; -using ModVerify.CliApp.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; using PG.StarWarsGame.Infrastructure.Mods; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal class ConsoleModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider) { diff --git a/src/ModVerify.CliApp/ModSelectors/IModSelector.cs b/src/ModVerify.CliApp/ModSelectors/IModSelector.cs index a713778..00f4c9e 100644 --- a/src/ModVerify.CliApp/ModSelectors/IModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/IModSelector.cs @@ -1,8 +1,8 @@ -using ModVerify.CliApp.Options; +using AET.ModVerifyTool.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal interface IModSelector { diff --git a/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs b/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs index 2d8abaf..08f6537 100644 --- a/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/ManualModSelector.cs @@ -1,9 +1,9 @@ using System; -using ModVerify.CliApp.Options; +using AET.ModVerifyTool.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal class ManualModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider) { diff --git a/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs b/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs index 6a2b442..861451a 100644 --- a/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs +++ b/src/ModVerify.CliApp/ModSelectors/ModSelectorBase.cs @@ -1,15 +1,16 @@ using System; using System.Collections.Generic; using System.Linq; +using AET.ModVerifyTool.GameFinder; +using AET.ModVerifyTool.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using ModVerify.CliApp.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; using PG.StarWarsGame.Infrastructure.Mods; using PG.StarWarsGame.Infrastructure.Services.Dependencies; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal abstract class ModSelectorBase : IModSelector { diff --git a/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs b/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs index 2afad15..8335a86 100644 --- a/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs +++ b/src/ModVerify.CliApp/ModSelectors/ModSelectorFactory.cs @@ -1,7 +1,7 @@ using System; -using ModVerify.CliApp.Options; +using AET.ModVerifyTool.Options; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal class ModSelectorFactory(IServiceProvider serviceProvider) { diff --git a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs index 684423a..356e6c2 100644 --- a/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs +++ b/src/ModVerify.CliApp/ModSelectors/SettingsBasedModSelector.cs @@ -2,16 +2,16 @@ using System.Globalization; using System.IO.Abstractions; using System.Linq; +using AET.ModVerifyTool.Options; using EawModinfo.Model; using EawModinfo.Spec; using Microsoft.Extensions.DependencyInjection; -using ModVerify.CliApp.Options; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Infrastructure; using PG.StarWarsGame.Infrastructure.Games; using PG.StarWarsGame.Infrastructure.Services.Name; -namespace ModVerify.CliApp.ModSelectors; +namespace AET.ModVerifyTool.ModSelectors; internal class SettingsBasedModSelector(IServiceProvider serviceProvider) { diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj index e1cf550..23518f7 100644 --- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj +++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj @@ -4,6 +4,8 @@ false net8.0;net48 Exe + AET.ModVerifyTool + ModVerify $(RepoRootPath)aet.ico AET.ModVerify.CommandLine AET.ModVerify diff --git a/src/ModVerify.CliApp/ModVerifyApp.cs b/src/ModVerify.CliApp/ModVerifyApp.cs index b6a8dda..598aa09 100644 --- a/src/ModVerify.CliApp/ModVerifyApp.cs +++ b/src/ModVerify.CliApp/ModVerifyApp.cs @@ -5,12 +5,12 @@ using System.Threading.Tasks; using AET.ModVerify; using AET.ModVerify.Reporting; +using AET.ModVerifyTool.ModSelectors; +using AET.ModVerifyTool.Options; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; -using ModVerify.CliApp.ModSelectors; -using ModVerify.CliApp.Options; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class ModVerifyApp(ModVerifyAppSettings settings, IServiceProvider services) { diff --git a/src/ModVerify.CliApp/ModVerifyPipeline.cs b/src/ModVerify.CliApp/ModVerifyPipeline.cs index 03fbfe3..a2a798c 100644 --- a/src/ModVerify.CliApp/ModVerifyPipeline.cs +++ b/src/ModVerify.CliApp/ModVerifyPipeline.cs @@ -7,7 +7,7 @@ using PG.StarWarsGame.Engine; using PG.StarWarsGame.Engine.Database; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class ModVerifyPipeline( GameEngineType targetType, diff --git a/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs b/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs index 9f2ad0f..667e2cf 100644 --- a/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs +++ b/src/ModVerify.CliApp/Options/GameInstallationsSettings.cs @@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis; using PG.StarWarsGame.Engine; -namespace ModVerify.CliApp.Options; +namespace AET.ModVerifyTool.Options; internal record GameInstallationsSettings { diff --git a/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs b/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs index 8b5e1bb..6c99bf4 100644 --- a/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs +++ b/src/ModVerify.CliApp/Options/ModVerifyAppSettings.cs @@ -1,8 +1,8 @@ using System; -using AET.ModVerify.Settings; using System.Diagnostics.CodeAnalysis; +using AET.ModVerify.Settings; -namespace ModVerify.CliApp.Options; +namespace AET.ModVerifyTool.Options; internal record ModVerifyAppSettings { diff --git a/src/ModVerify.CliApp/Options/ModVerifyOptions.cs b/src/ModVerify.CliApp/Options/ModVerifyOptions.cs index de9bb3a..65e3a9b 100644 --- a/src/ModVerify.CliApp/Options/ModVerifyOptions.cs +++ b/src/ModVerify.CliApp/Options/ModVerifyOptions.cs @@ -3,7 +3,7 @@ using CommandLine; using PG.StarWarsGame.Engine; -namespace ModVerify.CliApp.Options; +namespace AET.ModVerifyTool.Options; internal class ModVerifyOptions { diff --git a/src/ModVerify.CliApp/Program.cs b/src/ModVerify.CliApp/Program.cs index d7e1b89..ea5fff9 100644 --- a/src/ModVerify.CliApp/Program.cs +++ b/src/ModVerify.CliApp/Program.cs @@ -7,6 +7,7 @@ using AET.ModVerify.Reporting.Reporters; using AET.ModVerify.Reporting.Reporters.JSON; using AET.ModVerify.Reporting.Reporters.Text; +using AET.ModVerifyTool.Options; using AET.SteamAbstraction; using AnakinRaW.CommonUtilities.Hashing; using AnakinRaW.CommonUtilities.Registry; @@ -15,7 +16,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Console; -using ModVerify.CliApp.Options; using PG.Commons.Extensibility; using PG.StarWarsGame.Engine; using PG.StarWarsGame.Files.ALO; @@ -30,7 +30,7 @@ using Serilog.Events; using Serilog.Filters; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class Program { diff --git a/src/ModVerify.CliApp/SettingsBuilder.cs b/src/ModVerify.CliApp/SettingsBuilder.cs index f40ce30..eeba013 100644 --- a/src/ModVerify.CliApp/SettingsBuilder.cs +++ b/src/ModVerify.CliApp/SettingsBuilder.cs @@ -4,10 +4,10 @@ using System.IO.Abstractions; using AET.ModVerify.Reporting; using AET.ModVerify.Settings; +using AET.ModVerifyTool.Options; using Microsoft.Extensions.DependencyInjection; -using ModVerify.CliApp.Options; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class SettingsBuilder(IServiceProvider services) { diff --git a/src/ModVerify.CliApp/VerifyGameInstallationData.cs b/src/ModVerify.CliApp/VerifyGameInstallationData.cs index 8e157a5..69513ca 100644 --- a/src/ModVerify.CliApp/VerifyGameInstallationData.cs +++ b/src/ModVerify.CliApp/VerifyGameInstallationData.cs @@ -1,7 +1,7 @@ using System.Text; using PG.StarWarsGame.Engine; -namespace ModVerify.CliApp; +namespace AET.ModVerifyTool; internal class VerifyGameInstallationData { diff --git a/src/ModVerify/ModVerify.csproj b/src/ModVerify/ModVerify.csproj index d6ce1ec..4a77b42 100644 --- a/src/ModVerify/ModVerify.csproj +++ b/src/ModVerify/ModVerify.csproj @@ -7,6 +7,7 @@ Provides interfaces and classes to verify Empire at War / Forces of Corruption game modifications. AlamoEngineTools.ModVerify AET.ModVerify + AET.ModVerify alamo,petroglyph,glyphx From ec3b6d32ad8413237bf6f434c6f9724f7609a94e Mon Sep 17 00:00:00 2001 From: AnakinRaW Date: Sat, 3 Aug 2024 18:08:42 +0200 Subject: [PATCH 6/6] update dep --- src/ModVerify.CliApp/ModVerify.CliApp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ModVerify.CliApp/ModVerify.CliApp.csproj b/src/ModVerify.CliApp/ModVerify.CliApp.csproj index 23518f7..1fbe04f 100644 --- a/src/ModVerify.CliApp/ModVerify.CliApp.csproj +++ b/src/ModVerify.CliApp/ModVerify.CliApp.csproj @@ -25,8 +25,8 @@ runtime; build; native; contentfiles; analyzers; buildtransitive - - + + all