Skip to content

Commit 4e04252

Browse files
committed
start refactoring verification target selection
1 parent fdd9e38 commit 4e04252

22 files changed

Lines changed: 380 additions & 288 deletions

src/ModVerify.CliApp/GameFinder/GameFinderService.cs

Lines changed: 66 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.IO.Abstractions;
55
using Microsoft.Extensions.DependencyInjection;
66
using Microsoft.Extensions.Logging;
7+
using PG.StarWarsGame.Engine;
78
using PG.StarWarsGame.Infrastructure.Clients.Steam;
89
using PG.StarWarsGame.Infrastructure.Games;
910
using PG.StarWarsGame.Infrastructure.Mods;
@@ -12,6 +13,17 @@
1213

1314
namespace AET.ModVerify.App.GameFinder;
1415

16+
internal class GameFinderSettings
17+
{
18+
internal static readonly GameFinderSettings Default = new();
19+
20+
public bool InitMods { get; init; } = true;
21+
22+
public bool SearchFallbackGame { get; init; } = true;
23+
24+
public GameEngineType? Engine { get; init; } = null;
25+
}
26+
1527
internal class GameFinderService
1628
{
1729
private readonly IServiceProvider _serviceProvider;
@@ -29,18 +41,27 @@ public GameFinderService(IServiceProvider serviceProvider)
2941
_logger = _serviceProvider.GetService<ILoggerFactory>()?.CreateLogger(GetType());
3042
}
3143

32-
public GameFinderResult FindGames()
44+
public GameFinderResult FindGames(GameFinderSettings settings)
3345
{
3446
var detectors = new List<IGameDetector>
3547
{
3648
new DirectoryGameDetector(_fileSystem.DirectoryInfo.New(Environment.CurrentDirectory), _serviceProvider),
3749
new SteamPetroglyphStarWarsGameDetector(_serviceProvider),
3850
};
3951

40-
return FindGames(detectors);
52+
return FindGames(detectors, settings);
53+
}
54+
55+
public IGame FindGame(string gamePath, GameFinderSettings settings)
56+
{
57+
var detectors = new List<IGameDetector>
58+
{
59+
new DirectoryGameDetector(_fileSystem.DirectoryInfo.New(gamePath), _serviceProvider),
60+
};
61+
return FindGames(detectors, settings).Game;
4162
}
4263

43-
public GameFinderResult FindGamesFromPathOrGlobal(string path)
64+
public GameFinderResult FindGamesFromPathOrGlobal(string path, GameFinderSettings settings)
4465
{
4566
// There are four common situations:
4667
// 1. path points to the actual game directory
@@ -62,29 +83,10 @@ public GameFinderResult FindGamesFromPathOrGlobal(string path)
6283

6384
// Cases 3 & 4
6485
detectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider));
65-
return FindGames(detectors);
66-
}
67-
68-
private bool TryDetectGame(GameType gameType, IList<IGameDetector> detectors, out GameDetectionResult result)
69-
{
70-
var gd = new CompositeGameDetector(detectors, _serviceProvider);
71-
72-
try
73-
{
74-
result = gd.Detect(gameType);
75-
if (result.GameLocation is null)
76-
return false;
77-
return true;
78-
}
79-
catch (Exception e)
80-
{
81-
result = GameDetectionResult.NotInstalled(gameType);
82-
_logger?.LogTrace("Unable to find game installation: {Message}", e.Message);
83-
return false;
84-
}
86+
return FindGames(detectors, settings);
8587
}
86-
87-
private GameFinderResult FindGames(IList<IGameDetector> detectors)
88+
89+
private GameFinderResult FindGames(IList<IGameDetector> detectors, GameFinderSettings settings)
8890
{
8991
// FoC needs to be tried first
9092
if (!TryDetectGame(GameType.Foc, detectors, out var result))
@@ -102,34 +104,58 @@ private GameFinderResult FindGames(IList<IGameDetector> detectors)
102104

103105
var game = _gameFactory.CreateGame(result, CultureInfo.InvariantCulture);
104106

105-
SetupMods(game);
107+
if (settings.InitMods)
108+
SetupMods(game);
106109

107110

108111
IGame? fallbackGame = null;
109-
// If the game is Foc we want to set up Eaw as well as the fallbackGame
110-
if (game.Type == GameType.Foc)
112+
if (settings.SearchFallbackGame)
111113
{
112-
var fallbackDetectors = new List<IGameDetector>();
113-
114-
if (game.Platform == GamePlatform.SteamGold)
115-
fallbackDetectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider));
116-
else
117-
throw new NotImplementedException("Searching fallback game for non-Steam games is currently is not yet implemented.");
114+
// If the game is Foc we want to set up Eaw as well as the fallbackGame
115+
if (game.Type == GameType.Foc)
116+
{
117+
var fallbackDetectors = new List<IGameDetector>();
118+
119+
if (game.Platform == GamePlatform.SteamGold)
120+
fallbackDetectors.Add(new SteamPetroglyphStarWarsGameDetector(_serviceProvider));
121+
else
122+
throw new NotImplementedException("Searching fallback game for non-Steam games is currently is not yet implemented.");
118123

119-
if (!TryDetectGame(GameType.Eaw, fallbackDetectors, out var fallbackResult) || fallbackResult.GameLocation is null)
120-
throw new GameNotFoundException("Unable to find fallback game installation: Wrong install path?");
124+
if (!TryDetectGame(GameType.Eaw, fallbackDetectors, out var fallbackResult) || fallbackResult.GameLocation is null)
125+
throw new GameNotFoundException("Unable to find fallback game installation: Wrong install path?");
121126

122-
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
123-
"Found fallback game installation: {FallbackResultGameIdentity} at {GameLocationFullName}", fallbackResult.GameIdentity, fallbackResult.GameLocation.FullName);
127+
_logger?.LogInformation(ModVerifyConstants.ConsoleEventId,
128+
"Found fallback game installation: {FallbackResultGameIdentity} at {GameLocationFullName}", fallbackResult.GameIdentity, fallbackResult.GameLocation.FullName);
124129

125-
fallbackGame = _gameFactory.CreateGame(fallbackResult, CultureInfo.InvariantCulture);
130+
fallbackGame = _gameFactory.CreateGame(fallbackResult, CultureInfo.InvariantCulture);
126131

127-
SetupMods(fallbackGame);
132+
if (settings.InitMods)
133+
SetupMods(fallbackGame);
134+
}
128135
}
129136

130137
return new GameFinderResult(game, fallbackGame);
131138
}
132139

140+
private bool TryDetectGame(GameType gameType, IList<IGameDetector> detectors, out GameDetectionResult result)
141+
{
142+
var gd = new CompositeGameDetector(detectors, _serviceProvider);
143+
144+
try
145+
{
146+
result = gd.Detect(gameType);
147+
if (result.GameLocation is null)
148+
return false;
149+
return true;
150+
}
151+
catch (Exception e)
152+
{
153+
result = GameDetectionResult.NotInstalled(gameType);
154+
_logger?.LogTrace("Unable to find game installation: {Message}", e.Message);
155+
return false;
156+
}
157+
}
158+
133159
private void SetupMods(IGame game)
134160
{
135161
var modFinder = _serviceProvider.GetRequiredService<IModFinder>();

src/ModVerify.CliApp/ModSelectors/AutomaticModSelector.cs renamed to src/ModVerify.CliApp/ModSelectors/AutomaticSelector.cs

Lines changed: 51 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,92 +16,102 @@
1616

1717
namespace AET.ModVerify.App.ModSelectors;
1818

19-
internal class AutomaticModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider)
19+
internal class AutomaticSelector(IServiceProvider serviceProvider) : VerificationTargetSelectorBase(serviceProvider)
2020
{
2121
private readonly IFileSystem _fileSystem = serviceProvider.GetRequiredService<IFileSystem>();
2222

23-
public override GameLocations? Select(
24-
GameInstallationsSettings settings,
25-
out IPhysicalPlayableObject? targetObject,
26-
out GameEngineType? actualEngineType)
23+
public override VerificationTarget Select(GameInstallationsSettings settings)
2724
{
28-
var pathToVerify = settings.AutoPath;
29-
if (pathToVerify is null)
25+
var targetPath = settings.AutoPath;
26+
if (targetPath is null)
3027
throw new InvalidOperationException("path to verify cannot be null.");
3128

32-
actualEngineType = settings.EngineType;
29+
var engine = settings.Engine;
3330

3431
GameFinderResult finderResult;
3532
try
3633
{
37-
finderResult = GameFinderService.FindGamesFromPathOrGlobal(pathToVerify);
34+
finderResult = GameFinderService.FindGamesFromPathOrGlobal(targetPath, GameFinderSettings.Default);
3835
}
3936
catch (GameNotFoundException)
4037
{
41-
Logger?.LogError(ModVerifyConstants.ConsoleEventId, "Unable to find games based of the given location '{SettingsGamePath}'. Consider specifying all paths manually.", settings.GamePath);
42-
targetObject = null;
43-
return null;
38+
Logger?.LogError(ModVerifyConstants.ConsoleEventId, "Unable to find games based of the specified target path '{Path}'. Consider specifying all paths manually.", settings.GamePath);
39+
throw;
4440
}
4541

4642

47-
var modOrGame = GetAttachedModOrGame(finderResult, actualEngineType, pathToVerify);
43+
GameLocations locations;
44+
45+
var targetObject = GetAttachedModOrGame(finderResult, engine, targetPath);
4846

49-
if (modOrGame is not null)
47+
48+
if (targetObject is null)
5049
{
51-
var actualType = modOrGame.Game.Type.ToEngineType();
52-
actualEngineType ??= actualType;
53-
if (actualEngineType != actualType)
54-
throw new ArgumentException($"The specified game type '{actualEngineType}' does not match the actual type of the game or mod to verify.");
50+
if (!settings.Engine.HasValue)
51+
throw new ArgumentException("Game engine not specified. Use --engine argument to set it.");
5552

56-
targetObject = modOrGame;
57-
return GetLocations(targetObject, finderResult, settings.AdditionalFallbackPaths);
58-
}
53+
Logger?.LogDebug("The requested mod at '{TargetPath}' is detached from its games.", targetPath);
5954

60-
if (!settings.EngineType.HasValue)
61-
throw new ArgumentException("Unable to determine game type. Use --type argument to set the game type.");
55+
// The path is a detached mod, that exists on a different location than the game.
56+
locations = GetDetachedModLocations(targetPath, finderResult, settings, out var mod);
57+
targetObject = mod;
58+
}
59+
else
60+
{
61+
var actualType = targetObject.Game.Type.ToEngineType();
62+
engine ??= actualType;
63+
if (engine != actualType)
64+
throw new ArgumentException($"The specified game type '{engine}' does not match the actual type of the game or mod to verify.");
65+
locations = GetLocations(targetObject, finderResult.FallbackGame, settings.AdditionalFallbackPaths);
66+
}
6267

63-
Logger?.LogDebug("The requested mod at '{PathToVerify}' is detached from its games.", pathToVerify);
68+
return new VerificationTarget
69+
{
70+
Engine = engine.Value,
71+
Location = locations,
72+
Name = GetTargetName(targetObject, locations),
73+
Version = GetTargetVersion(targetObject)
74+
};
6475

65-
// The path is a detached mod, that exists on a different location than the game.
66-
var result = GetDetachedModLocations(pathToVerify, finderResult, settings, out var mod);
67-
targetObject = mod;
68-
return result;
6976
}
7077

71-
private IPhysicalPlayableObject? GetAttachedModOrGame(GameFinderResult finderResult, GameEngineType? requestedEngineType, string searchPath)
78+
private IPhysicalPlayableObject? GetAttachedModOrGame(GameFinderResult finderResult, GameEngineType? requestedEngineType, string targetPath)
7279
{
73-
var fullSearchPath = _fileSystem.Path.GetFullPath(searchPath);
80+
var targetFullPath = _fileSystem.Path.GetFullPath(targetPath);
7481

75-
if (finderResult.Game.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase))
82+
// If the target is the game directory itself.
83+
if (targetFullPath.Equals(finderResult.Game.Directory.FullName, StringComparison.OrdinalIgnoreCase))
7684
{
7785
if (finderResult.Game.Type.ToEngineType() != requestedEngineType)
78-
throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{searchPath}' to verify.");
86+
throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{targetPath}' to verify.");
7987
return finderResult.Game;
8088
}
8189

8290
if (finderResult.FallbackGame is not null &&
83-
finderResult.FallbackGame.Directory.FullName.Equals(fullSearchPath, StringComparison.OrdinalIgnoreCase))
91+
targetFullPath.Equals(finderResult.FallbackGame.Directory.FullName, StringComparison.OrdinalIgnoreCase))
8492
{
93+
throw new NotImplementedException("When does this actually happen???");
94+
8595
if (finderResult.FallbackGame.Type.ToEngineType() != requestedEngineType)
86-
throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{searchPath}' to verify.");
96+
throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the game '{targetPath}' to verify.");
8797
return finderResult.FallbackGame;
8898
}
8999

90-
return GetMatchingModFromGame(finderResult.Game, requestedEngineType, fullSearchPath) ??
91-
GetMatchingModFromGame(finderResult.FallbackGame, requestedEngineType, fullSearchPath);
100+
return GetMatchingModFromGame(finderResult.Game, requestedEngineType, targetFullPath) ??
101+
GetMatchingModFromGame(finderResult.FallbackGame, requestedEngineType, targetFullPath);
92102
}
93103

94104
private GameLocations GetDetachedModLocations(string modPath, GameFinderResult gameResult, GameInstallationsSettings settings, out IPhysicalMod mod)
95105
{
96106
IGame game = null!;
97107

98-
if (gameResult.Game.Type.ToEngineType() == settings.EngineType)
108+
if (gameResult.Game.Type.ToEngineType() == settings.Engine)
99109
game = gameResult.Game;
100-
if (gameResult.FallbackGame is not null && gameResult.FallbackGame.Type.ToEngineType() == settings.EngineType)
110+
if (gameResult.FallbackGame is not null && gameResult.FallbackGame.Type.ToEngineType() == settings.Engine)
101111
game = gameResult.FallbackGame;
102112

103113
if (game is null)
104-
throw new GameNotFoundException($"Unable to find game of type '{settings.EngineType}'");
114+
throw new GameNotFoundException($"Unable to find game of type '{settings.Engine}'");
105115

106116
var modFinder = ServiceProvider.GetRequiredService<IModFinder>();
107117
var modRef = modFinder.FindMods(game, _fileSystem.DirectoryInfo.New(modPath)).FirstOrDefault();
@@ -116,7 +126,7 @@ private GameLocations GetDetachedModLocations(string modPath, GameFinderResult g
116126

117127
mod.ResolveDependencies();
118128

119-
return GetLocations(mod, gameResult, settings.AdditionalFallbackPaths);
129+
return GetLocations(mod, gameResult.FallbackGame, settings.AdditionalFallbackPaths);
120130
}
121131

122132
private static IPhysicalMod? GetMatchingModFromGame(IGame? game, GameEngineType? requestedEngineType, string modPath)
@@ -132,7 +142,7 @@ private GameLocations GetDetachedModLocations(string modPath, GameFinderResult g
132142
if (physicalMod.Directory.FullName.Equals(modPath, StringComparison.OrdinalIgnoreCase))
133143
{
134144
if (!isGameSupported)
135-
throw new ArgumentException($"The specified game type '{requestedEngineType}' does not match the actual type of the mod '{modPath}' to verify.");
145+
throw new ArgumentException($"The specified engine type '{requestedEngineType}' does not match the required of the mod '{modPath}' to verify.");
136146
return physicalMod;
137147
}
138148
}

src/ModVerify.CliApp/ModSelectors/ConsoleModSelector.cs renamed to src/ModVerify.CliApp/ModSelectors/ConsoleSelector.cs

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,29 @@
55
using AET.ModVerify.App.Settings;
66
using AET.ModVerify.App.Utilities;
77
using AnakinRaW.ApplicationBase;
8-
using PG.StarWarsGame.Engine;
98
using PG.StarWarsGame.Infrastructure;
109
using PG.StarWarsGame.Infrastructure.Games;
1110
using PG.StarWarsGame.Infrastructure.Mods;
1211

1312
namespace AET.ModVerify.App.ModSelectors;
1413

15-
internal class ConsoleModSelector(IServiceProvider serviceProvider) : ModSelectorBase(serviceProvider)
14+
internal class ConsoleSelector(IServiceProvider serviceProvider) : VerificationTargetSelectorBase(serviceProvider)
1615
{
17-
public override GameLocations Select(
18-
GameInstallationsSettings settings,
19-
out IPhysicalPlayableObject targetObject,
20-
out GameEngineType? actualEngineType)
16+
public override VerificationTarget Select(GameInstallationsSettings settings)
2117
{
22-
var gameResult = GameFinderService.FindGames();
23-
targetObject = SelectPlayableObject(gameResult);
24-
actualEngineType = targetObject.Game.Type.ToEngineType();
25-
return GetLocations(targetObject, gameResult, settings.AdditionalFallbackPaths);
18+
var gameResult = GameFinderService.FindGames(GameFinderSettings.Default);
19+
var targetObject = SelectPlayableObject(gameResult);
20+
var engine = targetObject.Game.Type.ToEngineType();
21+
22+
var gameLocations = GetLocations(targetObject, gameResult.FallbackGame, settings.AdditionalFallbackPaths);
23+
24+
return new VerificationTarget
25+
{
26+
Engine = engine,
27+
Location = gameLocations,
28+
Name = GetTargetName(targetObject, gameLocations),
29+
Version = GetTargetVersion(targetObject)
30+
};
2631
}
2732

2833
private static IPhysicalPlayableObject SelectPlayableObject(GameFinderResult finderResult)

src/ModVerify.CliApp/ModSelectors/IModSelector.cs

Lines changed: 0 additions & 13 deletions
This file was deleted.
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
using AET.ModVerify.App.Settings;
2+
3+
namespace AET.ModVerify.App.ModSelectors;
4+
5+
internal interface IVerificationTargetSelector
6+
{
7+
VerificationTarget Select(GameInstallationsSettings settings);
8+
}

0 commit comments

Comments
 (0)