Skip to content

Commit

Permalink
Merge pull request #9 from tekgator/dev
Browse files Browse the repository at this point in the history
Restructure of code
  • Loading branch information
tekgator authored Aug 27, 2022
2 parents 27c48ac + f8ef79a commit 8dcca34
Show file tree
Hide file tree
Showing 26 changed files with 419 additions and 181 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file.

## [Unreleased]


## [1.1.0] - 2022-27-08
### Fixed
- disable 0649 to avoid compiler warning for MEF variables

### Added
- Add LauncherOptions to ILauncher interface to change settings on the fly for a single plugin
- Add Documentation to LauncherOptions
- Add Documentation to LauncherManager methods

### Changed
- Corrected Plugin documentation concerning referencing the Plugin ID
- Restructure of code
- Rename ClearCache method on LauncherManager and ILauncher Interface to Refresh
- LauncherManager will now always refresh all Plugins including the Games on initial GetLauncher call
- Remove GetGames method on ILauncher interface and instead add Games property


## [1.0.6] - 2022-24-08
### Fixed
- Origin plugin did not return working directory and executable name for online queries
Expand Down
12 changes: 9 additions & 3 deletions GameLib.Core/ILauncher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ namespace GameLib.Core;

public interface ILauncher
{
/// <summary>
/// The options the launcher manager has been provided with
/// </summary>
public LauncherOptions LauncherOptions { get; }

/// <summary>
/// Guid of the Launcher
/// NOTE: generated by the plugin
Expand Down Expand Up @@ -51,8 +56,9 @@ public interface ILauncher

/// <summary>
/// The installed games of the Launcher
/// NOTE: if no cache is available list will be empty, Refresh must be called first
/// </summary>
public IEnumerable<IGame> GetGames(CancellationToken cancellationToken = default);
public IEnumerable<IGame> Games { get; }

/// <summary>
/// Starts the launcher if not already running
Expand All @@ -66,7 +72,7 @@ public interface ILauncher
public void Stop();

/// <summary>
/// Clear any cached values so those get refreshed on next access
/// Clear any cached values and reload all launcher and game data
/// </summary>
public void ClearCache();
public void Refresh(CancellationToken cancellationToken = default);
}
11 changes: 11 additions & 0 deletions GameLib.Core/LauncherOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@

public class LauncherOptions
{
/// <summary>
/// Define if Launcher plugin should use local catalog data to get more detailed information about specific games
/// Note: Can in increase load time for the plugin
/// </summary>
public bool LoadLocalCatalogData { get; init; } = true;

/// <summary>
/// Define if Launcher plugin should use online query's to get more detailed information about specific games
/// Note: Can in increase load time for the plugin
/// </summary>
public bool QueryOnlineData { get; init; } = true;

/// <summary>
/// Defines the timeout time for online query's
/// </summary>
public TimeSpan? OnlineQueryTimeout { get; init; } = null;
}
16 changes: 8 additions & 8 deletions GameLib.Demo/GameLib.Demo.Console/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,28 +5,26 @@

foreach (var launcher in launcherManager.GetLaunchers())
{
var name = launcher.Name;
SetConsoleColor(ConsoleColor.White, ConsoleColor.Red);
Console.WriteLine($"\n{name}:");
Console.WriteLine($"\n{launcher.Name}:");
ResetConsoleColor();

foreach (var item in launcher.GetType().GetProperties().Where(p => p.Name != "Name"))
foreach (var property in launcher.GetType().GetProperties().Where(p => p.Name != "Name"))
{
Console.WriteLine($"\t{item.Name}: {item.GetValue(launcher)}");
Console.WriteLine($"\t{property.Name}: {property.GetValue(launcher)}");
}

var games = launcher.GetGames();
SetConsoleColor(ConsoleColor.Green);
Console.WriteLine("\n\tGames:");
ResetConsoleColor();
foreach (var game in games)
foreach (var game in launcher.Games)
{
SetConsoleColor(ConsoleColor.Magenta);
Console.WriteLine($"\tGame ID: {game.Id}");
ResetConsoleColor();
foreach (var item in game.GetType().GetProperties().Where(p => p.Name != "GameId"))
foreach (var property in game.GetType().GetProperties().Where(p => p.Name != "GameId"))
{
Console.WriteLine($"\t\t{item.Name}: {item.GetValue(game)}");
Console.WriteLine($"\t\t{property.Name}: {property.GetValue(game)}");
}
}
}
Expand All @@ -35,7 +33,9 @@ static void SetConsoleColor(ConsoleColor foregroundColor, ConsoleColor? backgrou
{
Console.ForegroundColor = foregroundColor;
if (backgroundColor is not null)
{
Console.BackgroundColor = (ConsoleColor)backgroundColor;
}
}

static void ResetConsoleColor()
Expand Down
24 changes: 22 additions & 2 deletions GameLib.Plugin/GameLib.Plugin.Epic/EpicGameFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Gamelib.Core.Util;
using GameLib.Core;
using GameLib.Plugin.Epic.Model;
using Microsoft.Win32;
using Newtonsoft.Json;
Expand All @@ -7,21 +8,32 @@ namespace GameLib.Plugin.Epic;

internal static class EpicGameFactory
{
public static IEnumerable<EpicGame> GetGames(Guid launcherId, CancellationToken cancellationToken = default)
public static IEnumerable<EpicGame> GetGames(ILauncher launcher, CancellationToken cancellationToken = default)
{
var metaDataDir = GetMetadataDir();
if (string.IsNullOrEmpty(metaDataDir))
{
return Enumerable.Empty<EpicGame>();
}

return Directory.GetFiles(metaDataDir, "*.item")
.AsParallel()
.WithCancellation(cancellationToken)
.Select(DeserializeManifest)
.Where(game => game is not null)
.Select(game => { game!.LauncherId = launcherId; return game; })
.Select(game => AddLauncherId(launcher, game!))
.ToList()!;
}

/// <summary>
/// Add launcher ID to Game
/// </summary>
private static EpicGame AddLauncherId(ILauncher launcher, EpicGame game)
{
game.LauncherId = launcher.Id;
return game;
}

/// <summary>
/// Get the meta data directory from registry; if not found try to locate in Common Application data
/// </summary>
Expand All @@ -35,13 +47,19 @@ public static IEnumerable<EpicGame> GetGames(Guid launcherId, CancellationToken

metadataDir = PathUtil.Sanitize(metadataDir);
if (string.IsNullOrEmpty(metadataDir))
{
return null;
}

if (!metadataDir.EndsWith("Manifests", StringComparison.OrdinalIgnoreCase))
{
metadataDir = Path.Combine(metadataDir, "Manifests");
}

if (!Directory.Exists(metadataDir))
{
return null;
}

return metadataDir;
}
Expand All @@ -57,7 +75,9 @@ public static IEnumerable<EpicGame> GetGames(Guid launcherId, CancellationToken
var manifestJson = File.ReadAllText(manifestFile);
deserializedEpicGame = JsonConvert.DeserializeObject<DeserializedEpicGame>(manifestJson);
if (deserializedEpicGame is null)
{
throw new ApplicationException("Cannot deserialize JSON stream");
}
}
catch { return null; }

Expand Down
26 changes: 13 additions & 13 deletions GameLib.Plugin/GameLib.Plugin.Epic/EpicLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Gamelib.Core.Util;
using GameLib.Core;
using GameLib.Plugin.Epic.Model;
using Microsoft.Win32;
using System.ComponentModel.Composition;
using System.Drawing;
Expand All @@ -12,14 +11,15 @@ namespace GameLib.Plugin.Epic;
[Export(typeof(ILauncher))]
public class EpicLauncher : ILauncher
{
private IEnumerable<EpicGame>? _gameList;

public EpicLauncher()
[ImportingConstructor]
public EpicLauncher(LauncherOptions? launcherOptions)
{
ClearCache();
LauncherOptions = launcherOptions ?? new LauncherOptions();
}

#region Interface implementations
public LauncherOptions LauncherOptions { get; }

public Guid Id => GetType().GUID;

public string Name => "Epic Games";
Expand All @@ -36,35 +36,33 @@ public EpicLauncher()

public string Executable { get; private set; } = string.Empty;

public IEnumerable<IGame> GetGames(CancellationToken cancellationToken = default)
{
_gameList ??= EpicGameFactory.GetGames(Id, cancellationToken);
return _gameList;
}
public IEnumerable<IGame> Games { get; private set; } = Enumerable.Empty<IGame>();

public bool Start() => IsRunning || ProcessUtil.StartProcess(ExecutablePath);

public void Stop()
{
if (IsRunning)
{
ProcessUtil.StopProcess(ExecutablePath);
}
}

public void ClearCache()
public void Refresh(CancellationToken cancellationToken = default)
{
_gameList = null;

ExecutablePath = string.Empty;
Executable = string.Empty;
InstallDir = string.Empty;
IsInstalled = false;
Games = Enumerable.Empty<IGame>();

ExecutablePath = GetExecutable() ?? string.Empty;
if (!string.IsNullOrEmpty(ExecutablePath))
{
Executable = Path.GetFileName(ExecutablePath);
InstallDir = Path.GetDirectoryName(ExecutablePath) ?? string.Empty;
IsInstalled = File.Exists(ExecutablePath);
Games = EpicGameFactory.GetGames(this, cancellationToken);
}
}
#endregion
Expand All @@ -80,7 +78,9 @@ public void ClearCache()
executablePath = PathUtil.Sanitize(executablePath);

if (!PathUtil.IsExecutable(executablePath))
{
executablePath = null;
}

return executablePath;
}
Expand Down
8 changes: 4 additions & 4 deletions GameLib.Plugin/GameLib.Plugin.Epic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,16 +26,16 @@ var launcherManager = new LauncherManager();
// not required to cast here just to add to the documentation
var launcher = (EpicLauncher?)launcherManager.GetLaunchers()
.Where(launcher => launcher.Name == "Epic Games")
// GUID of the class could also be used instead of the name
//.Where(launcher => launcher.GetType().GUID == new Guid("282B9BB6-54CA-4293-83CF-6F1134CDEEC6"))
// Plugin ID could also be used instead of the name
//.Where(launcher => launcher.Id == new Guid("282B9BB6-54CA-4293-83CF-6F1134CDEEC6"))
.FirstOrDefault();

if (launcher is not null)
{
var games = (IEnumerable<EpicGame>)launcher.GetGames();
var games = (IEnumerable<EpicGame>)launcher.Games;
foreach (var game in games)
{
// Write addtional data Epic Games is providing for a game besides from the IGame inteface
// Write additional data Epic Games is providing for a game besides from the IGame interface
Console.WriteLine($"\nGame");
Console.WriteLine($"\tInstallSize: {game.InstallSize}");
Console.WriteLine($"\tVersion: {game.Version}");
Expand Down
24 changes: 21 additions & 3 deletions GameLib.Plugin/GameLib.Plugin.Gog/GogGameFactory.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Gamelib.Core.Util;
using GameLib.Core;
using GameLib.Plugin.Gog.Model;
using Microsoft.Win32;
using System.Globalization;
Expand All @@ -10,30 +11,43 @@ internal static class GogGameFactory
/// <summary>
/// Get games installed for the GoG launcher
/// </summary>
public static IEnumerable<GogGame> GetGames(Guid launcherId, string launcherExecutable, CancellationToken cancellationToken = default)
public static IEnumerable<GogGame> GetGames(ILauncher launcher, CancellationToken cancellationToken = default)
{
using var regKey = RegistryUtil.GetKey(RegistryHive.LocalMachine, @"SOFTWARE\GOG.com\Games", true);

if (regKey is null)
{
return Enumerable.Empty<GogGame>();
}

return regKey.GetSubKeyNames()
.AsParallel()
.WithCancellation(cancellationToken)
.Select(gameId => LoadFromRegistry(launcherExecutable, gameId))
.Select(gameId => LoadFromRegistry(launcher.ExecutablePath, gameId))
.Where(game => game is not null)
.Select(game => { game!.LauncherId = launcherId; return game; })
.Select(game => AddLauncherId(launcher, game!))
.ToList()!;
}

/// <summary>
/// Add launcher ID to Game
/// </summary>
private static GogGame AddLauncherId(ILauncher launcher, GogGame game)
{
game.LauncherId = launcher.Id;
return game;
}

/// <summary>
/// Load the GoG game registry entry into a <see cref="GogGame"/> object
/// </summary>
private static GogGame? LoadFromRegistry(string launcherExecutable, string gameId)
{
using var regKey = RegistryUtil.GetKey(RegistryHive.LocalMachine, $@"SOFTWARE\GOG.com\Games\{gameId}");
if (regKey is null)
{
return null;
}

var game = new GogGame()
{
Expand Down Expand Up @@ -65,12 +79,16 @@ public static IEnumerable<GogGame> GetGames(Guid launcherId, string launcherExec
};

if (string.IsNullOrEmpty(game.Id))
{
return null;
}

game.InstallDir = Path.GetDirectoryName(game.ExecutablePath) ?? string.Empty;
game.LaunchString = $"\"{launcherExecutable}\" /command=runGame /gameId={game.Id}";
if (!string.IsNullOrEmpty(game.WorkingDir))
{
game.LaunchString += $" /path=\"{game.WorkingDir}\"";
}

return game;
}
Expand Down
Loading

0 comments on commit 8dcca34

Please sign in to comment.