Skip to content

Commit f08c274

Browse files
committed
local files handling refactoring
1 parent 00f856a commit f08c274

88 files changed

Lines changed: 8575 additions & 4533 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/Addons/Addons/BaseAddon.cs

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using Core.All;
44
using Core.All.Enums;
55
using Core.All.Interfaces;
6+
using Core.Client.Helpers;
67

78
namespace Addons.Addons;
89

@@ -16,13 +17,18 @@ public abstract class BaseAddon
1617
/// </summary>
1718
public required AddonId AddonId { get; init; }
1819

20+
/// <summary>
21+
/// Addon file information.
22+
/// </summary>
23+
public required AddonFilePathWrapper? FileInfo { get; init; }
24+
1925
/// <summary>
2026
/// Type of the addon
2127
/// </summary>
2228
public required AddonTypeEnum Type { get; init; }
2329

2430
/// <summary>
25-
/// List of supported games
31+
/// Supported game
2632
/// </summary>
2733
public required GameInfo SupportedGame { get; init; }
2834

@@ -61,11 +67,6 @@ public abstract class BaseAddon
6167
/// </summary>
6268
public required IReadOnlyDictionary<string, string?>? IncompatibleAddons { get; init; }
6369

64-
/// <summary>
65-
/// Path to addon file
66-
/// </summary>
67-
public required string? PathToFile { get; init; }
68-
6970
/// <summary>
7071
/// Cover image hash
7172
/// </summary>
@@ -91,11 +92,6 @@ public abstract class BaseAddon
9192
/// </summary>
9293
public required IStartMap? StartMap { get; init; }
9394

94-
/// <summary>
95-
/// Is addon unpacked to a folder
96-
/// </summary>
97-
public required bool IsUnpacked { get; init; }
98-
9995
/// <summary>
10096
/// Is the item marked as a favorite.
10197
/// </summary>
@@ -116,11 +112,6 @@ public abstract class BaseAddon
116112
/// </summary>
117113
public required Dictionary<string, Dictionary<string, OptionalParameterTypeEnum>>? Options { get; init; }
118114

119-
/// <summary>
120-
/// Name of the addon file
121-
/// </summary>
122-
public string? FileName => PathToFile is null ? null : Path.GetFileName(PathToFile);
123-
124115
/// <inheritdoc/>
125116
public override string ToString() => Title;
126117

src/Addons/Helpers/AddonDropHelper.cs

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
using Microsoft.Extensions.Logging;
66
using SharpCompress.Archives;
77

8+
namespace Addons.Helpers;
9+
810
public interface IAddonDropHelper
911
{
1012
/// <summary>
@@ -19,11 +21,17 @@ public interface IAddonDropHelper
1921
public sealed class AddonDropHelper : IAddonDropHelper
2022
{
2123
private readonly InstalledAddonsProviderFactory _installedAddonsProvider;
24+
private readonly LocalFilesProvider _addonScanner;
2225
private readonly ILogger<AddonDropHelper> _logger;
2326

24-
public AddonDropHelper(InstalledAddonsProviderFactory installedAddonsProvider, ILogger<AddonDropHelper> logger)
27+
public AddonDropHelper(
28+
InstalledAddonsProviderFactory installedAddonsProvider,
29+
LocalFilesProvider addonScanner,
30+
ILogger<AddonDropHelper> logger
31+
)
2532
{
2633
_installedAddonsProvider = installedAddonsProvider;
34+
_addonScanner = addonScanner;
2735
_logger = logger;
2836
}
2937

@@ -35,21 +43,19 @@ public AddonDropHelper(InstalledAddonsProviderFactory installedAddonsProvider, I
3543
return null;
3644
}
3745

38-
List<string> failedInstalls = [];
46+
List<string>? failedInstalls = null;
3947

4048
foreach (var file in filePaths)
4149
{
4250
var isAdded = await AddAddonAsync(file, game).ConfigureAwait(false);
4351

44-
if (!isAdded)
52+
if (isAdded)
4553
{
46-
failedInstalls.Add(Path.GetFileName(file));
54+
continue;
4755
}
48-
}
4956

50-
if (failedInstalls.Count == 0)
51-
{
52-
return null;
57+
failedInstalls ??= [];
58+
failedInstalls.Add(Path.GetFileName(file));
5359
}
5460

5561
return failedInstalls;
@@ -71,7 +77,7 @@ private async Task<bool> AddAddonAsync(string pathToFile, BaseGame game)
7177
return false;
7278
}
7379

74-
var addon = await GetGameAndTypeFromFileAsync(pathToFile, game).ConfigureAwait(false);
80+
var addon = await GetGameAndTypeFromFileAsync(pathToFile, game.GameEnum).ConfigureAwait(false);
7581

7682
if (addon is null)
7783
{
@@ -109,8 +115,19 @@ private async Task<bool> AddAddonAsync(string pathToFile, BaseGame game)
109115

110116
File.Copy(pathToFile, newPathToFile, true);
111117

112-
using var installer = _installedAddonsProvider.Get(game);
113-
await installer.AddAddonAsync(newPathToFile).ConfigureAwait(false);
118+
var parsedFiles = await _addonScanner.TryAddFileToCache(newPathToFile, game.GameEnum).ConfigureAwait(false);
119+
120+
if (parsedFiles is null)
121+
{
122+
return false;
123+
}
124+
125+
var installer = _installedAddonsProvider.Get(game);
126+
127+
foreach (var parsed in parsedFiles)
128+
{
129+
installer.AddAddon(parsed);
130+
}
114131

115132
return true;
116133
}
@@ -119,7 +136,8 @@ private async Task<bool> AddAddonAsync(string pathToFile, BaseGame game)
119136
/// Get game enum and addon type enum from a file.
120137
/// </summary>
121138
/// <param name="pathToFile">Path to file.</param>
122-
private async Task<Tuple<GameEnum, AddonTypeEnum>?> GetGameAndTypeFromFileAsync(string pathToFile, BaseGame game)
139+
/// <param name="gameEnum">The game to associate with standalone .map files.</param>
140+
private async Task<Tuple<GameEnum, AddonTypeEnum>?> GetGameAndTypeFromFileAsync(string pathToFile, GameEnum gameEnum)
123141
{
124142
if (ArchiveFactory.IsArchive(pathToFile, out _))
125143
{
@@ -138,7 +156,7 @@ private async Task<bool> AddAddonAsync(string pathToFile, BaseGame game)
138156

139157
if (pathToFile.EndsWith(".map", StringComparison.OrdinalIgnoreCase))
140158
{
141-
return new(game.GameEnum, AddonTypeEnum.Map);
159+
return new(gameEnum, AddonTypeEnum.Map);
142160
}
143161

144162
return null;

src/Addons/Helpers/AutoloadModsValidator.cs

Lines changed: 48 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Addons.Addons;
2-
using Core.All;
32
using Core.All.Enums;
43
using Core.All.Helpers;
54

@@ -14,7 +13,7 @@ public static class AutoloadModsValidator
1413
/// <param name="campaign">Campaign</param>
1514
/// <param name="mods">Autoload mods</param>
1615
/// <param name="features">Features supported by the port</param>
17-
public static bool ValidateAutoloadMod(AutoloadMod autoloadMod, BaseAddon campaign, IReadOnlyDictionary<AddonId, BaseAddon> mods, List<FeatureEnum> features)
16+
public static bool ValidateAutoloadMod(AutoloadMod autoloadMod, BaseAddon campaign, IReadOnlyList<BaseAddon> mods, List<FeatureEnum> features)
1817
{
1918
if (!autoloadMod.IsEnabled)
2019
{
@@ -41,7 +40,7 @@ public static bool ValidateAutoloadMod(AutoloadMod autoloadMod, BaseAddon campai
4140
return false;
4241
}
4342

44-
//check if campaign is incomatible with this or all addons
43+
//check if campaign is incompatible with this or all addons
4544
if (campaign.IncompatibleAddons is not null)
4645
{
4746
foreach (var incompatibleAddon in campaign.IncompatibleAddons)
@@ -84,52 +83,49 @@ public static bool ValidateAutoloadMod(AutoloadMod autoloadMod, BaseAddon campai
8483
private static bool CheckDependencies(
8584
AutoloadMod autoloadMod,
8685
BaseAddon campaign,
87-
IReadOnlyDictionary<AddonId, BaseAddon> mods)
86+
IReadOnlyList<BaseAddon> mods
87+
)
8888
{
89-
if (autoloadMod.DependentAddons is not null)
89+
if (autoloadMod.DependentAddons is null)
9090
{
91-
byte passedDependenciesCount = 0;
91+
return true;
92+
}
93+
94+
byte passedDependenciesCount = 0;
9295

93-
foreach (var dependentAddon in autoloadMod.DependentAddons)
96+
foreach (var dependentAddon in autoloadMod.DependentAddons)
97+
{
98+
if (campaign.AddonId.Id.Equals(dependentAddon.Key, StringComparison.OrdinalIgnoreCase) &&
99+
(dependentAddon.Value is null || VersionComparer.Compare(campaign.AddonId.Version, dependentAddon.Value)))
94100
{
95-
if (campaign.AddonId.Id.Equals(dependentAddon.Key, StringComparison.OrdinalIgnoreCase) &&
96-
(dependentAddon.Value is null || VersionComparer.Compare(campaign.AddonId.Version, dependentAddon.Value)))
97-
{
98-
passedDependenciesCount++;
99-
continue;
100-
}
101+
passedDependenciesCount++;
102+
continue;
103+
}
104+
105+
if (campaign.DependentAddons is not null &&
106+
campaign.DependentAddons.TryGetValue(dependentAddon.Key, out var dependentAddonVersion) &&
107+
(dependentAddon.Value is null || VersionComparer.Compare(dependentAddonVersion, dependentAddon.Value)))
108+
{
109+
passedDependenciesCount++;
110+
continue;
111+
}
101112

102-
if (campaign.DependentAddons?.TryGetValue(dependentAddon.Key, out var dependentAddonVersion) ?? false &&
103-
(dependentAddon.Value is null || VersionComparer.Compare(dependentAddonVersion, dependentAddon.Value)))
113+
foreach (var addon in mods)
114+
{
115+
if (!dependentAddon.Key.Equals(addon.AddonId.Id, StringComparison.InvariantCultureIgnoreCase))
104116
{
105-
passedDependenciesCount++;
106117
continue;
107118
}
108119

109-
foreach (var addon in mods)
120+
if (dependentAddon.Value is null || VersionComparer.Compare(addon.AddonId.Version, dependentAddon.Value))
110121
{
111-
if (!dependentAddon.Key.Equals(addon.Key.Id, StringComparison.OrdinalIgnoreCase))
112-
{
113-
continue;
114-
}
115-
116-
if (dependentAddon.Value is null)
117-
{
118-
passedDependenciesCount++;
119-
}
120-
else if (VersionComparer.Compare(addon.Key.Version, dependentAddon.Value))
121-
{
122-
passedDependenciesCount++;
123-
}
122+
passedDependenciesCount++;
124123
}
125124
}
126-
127-
return autoloadMod.DependentAddons.Count == passedDependenciesCount;
128-
}
129-
else
130-
{
131-
return true;
132125
}
126+
127+
return autoloadMod.DependentAddons.Count == passedDependenciesCount;
128+
133129
}
134130

135131
/// <summary>
@@ -138,30 +134,32 @@ private static bool CheckDependencies(
138134
private static bool CheckIncompatibles(
139135
AutoloadMod autoloadMod,
140136
BaseAddon campaign,
141-
IReadOnlyDictionary<AddonId, BaseAddon> mods
137+
IReadOnlyList<BaseAddon> mods
142138
)
143139
{
144140
var campaignIncompatibles = campaign.IncompatibleAddons?.ToDictionary() ?? [];
145141
campaignIncompatibles.Add(campaign.AddonId.Id, campaign.AddonId.Version);
146-
campaignIncompatibles.AddRange(mods.Where(x => x.Value is AutoloadMod { IsEnabled: true }).ToDictionary(x => x.Key.Id, x => x.Key.Version));
142+
campaignIncompatibles.AddRange(mods.Where(x => x is AutoloadMod { IsEnabled: true }).ToDictionary(x => x.AddonId.Id, x => x.AddonId.Version));
147143

148-
if (autoloadMod.IncompatibleAddons is not null)
144+
if (autoloadMod.IncompatibleAddons is null)
149145
{
150-
foreach (var a in campaignIncompatibles)
146+
return true;
147+
}
148+
149+
foreach (var a in campaignIncompatibles)
150+
{
151+
foreach (var b in autoloadMod.IncompatibleAddons)
151152
{
152-
foreach (var b in autoloadMod.IncompatibleAddons)
153+
if (!a.Key.Equals(b.Key, StringComparison.OrdinalIgnoreCase))
153154
{
154-
if (!a.Key.Equals(b.Key, StringComparison.OrdinalIgnoreCase))
155-
{
156-
continue;
157-
}
155+
continue;
156+
}
158157

159-
var areEqual = VersionComparer.Compare(a.Value, b.Value);
158+
var areEqual = VersionComparer.Compare(a.Value, b.Value);
160159

161-
if (areEqual)
162-
{
163-
return false;
164-
}
160+
if (areEqual)
161+
{
162+
return false;
165163
}
166164
}
167165
}

src/Addons/Helpers/DiHelper.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using Addons.Providers;
2-
using Core.Client.Providers;
32
using Microsoft.Extensions.DependencyInjection;
43

54
namespace Addons.Helpers;
@@ -15,6 +14,7 @@ public static IServiceCollection WithAddons(this IServiceCollection container)
1514
_ = container.AddSingleton<DownloadableAddonsProviderFactory>();
1615
_ = container.AddSingleton<OriginalCampaignsProvider>();
1716
_ = container.AddSingleton<MetadataProvider>();
17+
_ = container.AddSingleton<LocalFilesProvider>();
1818

1919
return container.AddTransient<IAddonDropHelper, AddonDropHelper>();
2020
}

0 commit comments

Comments
 (0)