Skip to content

Commit

Permalink
Merge pull request #37 from KrystianLesniak/develop
Browse files Browse the repository at this point in the history
Release: 1.6.0
  • Loading branch information
KrystianLesniak committed Nov 6, 2023
2 parents fa2d514 + b1b430d commit c167d0e
Show file tree
Hide file tree
Showing 15 changed files with 214 additions and 91 deletions.
2 changes: 1 addition & 1 deletion src/GamesLauncher.Common/Settings/HiddenGames.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public class HiddenGames
Platform = "Steam",
Title = "Steamworks Common Redistributables"
}
};
};

public void Hide(string title, string platform, string internalGameId)
{
Expand Down
42 changes: 32 additions & 10 deletions src/GamesLauncher.Platforms/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,47 @@ namespace GamesLauncher.Platforms
{
public class Game
{
internal Game(string Title,
Func<ActionContext, ValueTask<bool>> RunTask,
string? IconPath,
IconDelegate? IconDelegate,
string Platform)
internal Game(string title,
Func<ActionContext, ValueTask<bool>> runTask,
string? iconPath,
IconDelegate? iconDelegate,
string platform,
UninstallAction? uninstallAction = null)
{
this.Title = Title;
this.RunTask = RunTask;
this.IconPath = IconPath;
this.IconDelegate = IconDelegate;
this.Platform = Platform;
Title = title;
RunTask = runTask;
IconPath = iconPath;
IconDelegate = iconDelegate;
Platform = platform;
UninstallAction = uninstallAction;
}

public string Title { get; }
public Func<ActionContext, ValueTask<bool>> RunTask { get; }
public UninstallAction? UninstallAction { get; }
public string? IconPath { get; }
public IconDelegate? IconDelegate { get; }
public string Platform { get; }
public string InternalGameId => $"{Platform}_{Title}";

}

public class UninstallAction
{
public string Title { get; } = "Uninstall";

public Func<Task> UninstallTask { get; }

internal UninstallAction(Func<Task> uninstallTask)
{
UninstallTask = uninstallTask;
}

internal UninstallAction(Func<Task> uninstallTask, string title)
{
Title = title;
UninstallTask = uninstallTask;
}

}
}
4 changes: 2 additions & 2 deletions src/GamesLauncher.Platforms/GamesLauncher.Platforms.csproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0-windows</TargetFramework>
Expand All @@ -20,7 +20,7 @@
<PackageReference Include="GameFinder.StoreHandlers.Steam" Version="4.0.0" />
<PackageReference Include="GameFinder.StoreHandlers.Xbox" Version="4.0.0" />
<PackageReference Include="Microsoft-WindowsAPICodePack-Shell" Version="1.1.5" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.12" />
<PackageReference Include="Microsoft.Data.Sqlite" Version="7.0.13" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
</ItemGroup>

Expand Down
42 changes: 18 additions & 24 deletions src/GamesLauncher.Platforms/PlatformsManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@
using GamesLauncher.Platforms.SyncEngines.Amazon;
using GamesLauncher.Platforms.SyncEngines.Epic;
using GamesLauncher.Platforms.SyncEngines.Steam;
using System.Collections.Concurrent;
using System.Diagnostics;

namespace GamesLauncher.Platforms
{
public class PlatformsManager
{
private IEnumerable<Game> Games = Array.Empty<Game>();
public IEnumerable<Game> AllSynchronizedGames => Engines.SelectMany(x => x.SynchronizedGames);

private IEnumerable<ISyncEngine> Engines { get; set; } = Array.Empty<ISyncEngine>();

private readonly IPublicAPI publicApi;

Expand All @@ -21,18 +23,25 @@ public PlatformsManager(IPublicAPI publicApi)

public async Task SynchronizeGames(MainSettings settings)
{
var engines = InitializeEngines(settings);
Games = await SynchronizeLibraries(engines);
}
#if DEBUG
var stopwatch = Stopwatch.StartNew();
#endif

public IEnumerable<Game> GetSynchronizedGames()
{
return Games;
Engines = InitializeEngines(settings);
await Parallel.ForEachAsync(Engines, async (engine, ct) =>
{
await engine.SynchronizeGames();
});

#if DEBUG
stopwatch.Stop();
publicApi.LogInfo(nameof(PlatformsManager), $"GamesLauncher: Games synchronization time: {stopwatch.Elapsed}");
#endif
}

public Game? GetGame(string title, string platform)
{
return Games.FirstOrDefault(x=> x.Title == title && x.Platform == platform);
return AllSynchronizedGames.FirstOrDefault(x => x.Title == title && x.Platform == platform);
}

private IEnumerable<ISyncEngine> InitializeEngines(MainSettings settings)
Expand All @@ -55,20 +64,5 @@ private IEnumerable<ISyncEngine> InitializeEngines(MainSettings settings)

return engines;
}

private static async Task<IEnumerable<Game>> SynchronizeLibraries(IEnumerable<ISyncEngine> engines)
{
var games = new ConcurrentBag<Game>();

await Parallel.ForEachAsync(engines, async (engine, ct) =>
{
await foreach (var game in engine.GetGames())
{
games.Add(game);
};
});

return games;
}
}
}
23 changes: 15 additions & 8 deletions src/GamesLauncher.Platforms/SyncEngines/Amazon/AmazonSyncEngine.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
using Flow.Launcher.Plugin;
using GamesLauncher.Platforms.SyncEngines.Amazon.Readers;
using System.Collections.Concurrent;

namespace GamesLauncher.Platforms.SyncEngines.Amazon
{
internal class AmazonSyncEngine : ISyncEngine
{
public string PlatformName => "Amazon Games";
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();


private readonly IPublicAPI publicApi;

Expand All @@ -14,21 +17,25 @@ public AmazonSyncEngine(IPublicAPI publicApi)
this.publicApi = publicApi;
}

public async IAsyncEnumerable<Game> GetGames()
public async Task SynchronizeGames()
{
await using var installInfoReader = new InstallInfoReader();
await using var productDetailsReader = new ProductDetailsReader();

var syncedGames = new ConcurrentBag<Game>();

await foreach (var gameInstallInfo in installInfoReader.GetInstalledGamesId())
{
yield return new Game(
Title: gameInstallInfo.Title,
RunTask: GetGameRunTask(gameInstallInfo.Id),
IconPath: await productDetailsReader.GetIconUrlById(gameInstallInfo.Id),
IconDelegate: null,
Platform: PlatformName
);
syncedGames.Add(new Game(
title: gameInstallInfo.Title,
runTask: GetGameRunTask(gameInstallInfo.Id),
iconPath: await productDetailsReader.GetIconUrlById(gameInstallInfo.Id),
iconDelegate: null,
platform: PlatformName
));
}

SynchronizedGames = syncedGames;
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
using Microsoft.Data.Sqlite;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Data;
using ErrorEventArgs = Newtonsoft.Json.Serialization.ErrorEventArgs;

Expand Down
28 changes: 16 additions & 12 deletions src/GamesLauncher.Platforms/SyncEngines/Epic/EpicSyncEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,35 +9,39 @@ namespace GamesLauncher.Platforms.SyncEngines.Epic
{
internal class EpicSyncEngine : ISyncEngine
{
private readonly IPublicAPI publicApi;

public string PlatformName => "Epic Games Launcher";
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();

private readonly IPublicAPI publicApi;

public EpicSyncEngine(IPublicAPI publicApi)
{
this.publicApi = publicApi;
}

public async IAsyncEnumerable<Game> GetGames()
public async Task SynchronizeGames()
{
var epicGames = await GetEpicGamesFromMetadata();

var syncedGames = new List<Game>();

foreach (var epicGame in epicGames)
{

yield return new Game(
Title: epicGame.DisplayName,
RunTask: PrepareRunTask(epicGame.CatalogNamespace, epicGame.CatalogItemId, epicGame.AppName),
IconPath: PrepareIconPath(epicGame),
Platform: PlatformName,
IconDelegate: null
);
syncedGames.Add(new Game(
title: epicGame.DisplayName,
runTask: PrepareRunTask(epicGame.CatalogNamespace, epicGame.CatalogItemId, epicGame.AppName),
iconPath: PrepareIconPath(epicGame),
platform: PlatformName,
iconDelegate: null
));
}

SynchronizedGames = syncedGames;
}

private static async Task<IEnumerable<EpicGame>> GetEpicGamesFromMetadata()
{
var metadataDir = (string?)Registry.GetValue(EpicGamesConsts.RegKeyPath, EpicGamesConsts.RegKeyValueName, string.Empty);
var metadataDir = Registry.GetValue(EpicGamesConsts.RegKeyPath, EpicGamesConsts.RegKeyValueName, string.Empty) as string;

if (string.IsNullOrEmpty(metadataDir))
return Array.Empty<EpicGame>();
Expand Down
3 changes: 2 additions & 1 deletion src/GamesLauncher.Platforms/SyncEngines/ISyncEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@
internal interface ISyncEngine
{
string PlatformName { get; }
IAsyncEnumerable<Game> GetGames();
IEnumerable<Game> SynchronizedGames { get; }
Task SynchronizeGames();
}
34 changes: 25 additions & 9 deletions src/GamesLauncher.Platforms/SyncEngines/ShortcutsSyncEngine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
namespace GamesLauncher.Platforms.SyncEngines
{
public class ShortcutsSyncEngine : ISyncEngine

{
public string PlatformName => "Shortcut";
public IEnumerable<Game> SynchronizedGames { get; private set; } = Array.Empty<Game>();

private readonly IPublicAPI publicApi;
private readonly DirectoryInfo shortcutsDirectory;
Expand All @@ -17,23 +17,30 @@ public ShortcutsSyncEngine(IPublicAPI publicApi)
shortcutsDirectory = Directory.CreateDirectory(Paths.CustomShortcutsDirectory);
}

public async IAsyncEnumerable<Game> GetGames()
public async Task SynchronizeGames()
{
string[] shortcutExtensions = { "*.url", "*.lnk" };
var syncedGames = new List<Game>();

foreach (var shortcutExtension in shortcutExtensions)
{
foreach (var shortcut in shortcutsDirectory.EnumerateFiles(shortcutExtension, SearchOption.AllDirectories))
{
yield return new Game(
Title: Path.GetFileNameWithoutExtension(shortcut.FullName),
RunTask: GetGameRunTask(shortcut.FullName),
IconPath: await GetIconPath(shortcut),
IconDelegate: null,
Platform: PlatformName
);
syncedGames.Add(new Game(
title: Path.GetFileNameWithoutExtension(shortcut.FullName),
runTask: GetGameRunTask(shortcut.FullName),
iconPath: await GetIconPath(shortcut),
iconDelegate: null,
platform: PlatformName,
uninstallAction: new(
GetShortcutDeleteTask(shortcut.FullName),
"Delete Shortcut"
)
));
}
}

SynchronizedGames = syncedGames;
}

private Func<ActionContext, ValueTask<bool>> GetGameRunTask(string fullPath)
Expand All @@ -46,6 +53,15 @@ private Func<ActionContext, ValueTask<bool>> GetGameRunTask(string fullPath)
};
}

private Func<Task> GetShortcutDeleteTask(string fullPath)
{
return async () =>
{
File.Delete(fullPath);
await SynchronizeGames();
};
}

private static async Task<string?> GetIconPath(FileInfo fileInfo)
{
if (fileInfo.Extension == ".url")
Expand Down
Loading

0 comments on commit c167d0e

Please sign in to comment.