diff --git a/Directory.Build.props b/Directory.Build.props index 1f06eb4..e82e6be 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 0.27.0 + 0.27.1 net9.0 enable latest diff --git a/Directory.Packages.props b/Directory.Packages.props index 25d6dbb..fbeb659 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -25,6 +25,7 @@ + diff --git a/src/Addons/Providers/InstalledAddonsProvider.cs b/src/Addons/Providers/InstalledAddonsProvider.cs index b712a8d..731f1c8 100644 --- a/src/Addons/Providers/InstalledAddonsProvider.cs +++ b/src/Addons/Providers/InstalledAddonsProvider.cs @@ -887,30 +887,30 @@ or GameEnum.NAM /// AddonDto private string? UnpackIfNeededAndGetAddonDto(string pathToFile, IArchive archive, out List? addonDtos) { - string? unpackedTo = null; - - if (archive.Entries.Any(static x => x.Key!.Equals("addons.grpinfo", StringComparison.OrdinalIgnoreCase))) + try { - //need to unpack archive with grpinfo - unpackedTo = Unpack(pathToFile, archive); - addonDtos = null; - return unpackedTo; - } + string? unpackedTo = null; - var addonJsons = archive.Entries.Where(static x => x.Key!.StartsWith("addon") && x.Key!.EndsWith(".json")); + if (archive.Entries.Any(static x => x.Key!.Equals("addons.grpinfo", StringComparison.OrdinalIgnoreCase))) + { + //need to unpack archive with grpinfo + unpackedTo = Unpack(pathToFile, archive); + addonDtos = null; + return unpackedTo; + } - if (addonJsons?.Any() is not true) - { - addonDtos = null; - return null; - } + var addonJsonsInsideArchive = archive.Entries.Where(static x => x.Key!.StartsWith("addon") && x.Key!.EndsWith(".json")); - try - { - using var stream = addonJsons.First().OpenEntryStream(); + if (addonJsonsInsideArchive?.Any() is not true) + { + addonDtos = null; + return null; + } + + using var addonJsonStream = addonJsonsInsideArchive.First().OpenEntryStream(); var addonDto = JsonSerializer.Deserialize( - stream, + addonJsonStream, AddonManifestContext.Default.AddonDto )!; @@ -925,29 +925,50 @@ or GameEnum.NAM //need to unpack addons with custom executables unpackedTo = Unpack(pathToFile, archive); } - } - catch - { - addonDtos = null; - return null; - } - List result = []; + List result = []; - foreach (var addonJson in addonJsons) - { - using var stream = addonJson.OpenEntryStream(); + if (unpackedTo is not null) + { + var unpackedAddonJsons = Directory.GetFiles(unpackedTo, "addon*.json"); - var addonDto = JsonSerializer.Deserialize( - stream, - AddonManifestContext.Default.AddonDto - )!; + foreach (var addonJson in unpackedAddonJsons) + { + var text = File.ReadAllText(addonJson); + + var addonDto2 = JsonSerializer.Deserialize( + text, + AddonManifestContext.Default.AddonDto + )!; + + result.Add(addonDto2); + } + } + else + { + foreach (var addonJson in addonJsonsInsideArchive) + { + using var addonJsonStream2 = addonJson.OpenEntryStream(); + + var addonDto2 = JsonSerializer.Deserialize( + addonJsonStream2, + AddonManifestContext.Default.AddonDto + )!; + + result.Add(addonDto2); + } + } - result.Add(addonDto); + addonDtos = result.Count > 0 ? result : null; + return unpackedTo; } + catch (Exception ex) + { + _logger.LogCritical(ex, "=== Error while unpacking archive ==="); - addonDtos = result.Count > 0 ? result : null; - return unpackedTo; + addonDtos = null; + return null; + } } /// diff --git a/src/Tests/AddonFilesTests.cs b/src/Tests/AddonFilesTests.cs new file mode 100644 index 0000000..6e96bc3 --- /dev/null +++ b/src/Tests/AddonFilesTests.cs @@ -0,0 +1,122 @@ +using Addons.Providers; +using Common; +using Common.Client.Interfaces; +using Common.Interfaces; +using Microsoft.Extensions.Logging; +using Moq; +using System.Reflection; + +namespace Tests; + +[Collection("Sync")] +public sealed class AddonFilesTests : IDisposable +{ + private readonly InstalledAddonsProvider _installedAddonsProvider; + private readonly MethodInfo _getAddonsFromFilesAsync; + + public AddonFilesTests() + { + var game = new Mock(); + var config = new Mock(); + _ = config.Setup(x => x.DisabledAutoloadMods).Returns([]); + var logger = new Mock(); + + _installedAddonsProvider = new(game.Object, config.Object, logger.Object); + _getAddonsFromFilesAsync = typeof(InstalledAddonsProvider).GetMethod("GetAddonsFromFilesAsync", BindingFlags.NonPublic | BindingFlags.Instance)!; + } + + public void Dispose() + { + Directory.Delete("FilesTemp", true); + } + + + [Fact] + public async Task AddonArchiveTest() + { + _ = Directory.CreateDirectory("FilesTemp"); + File.Copy(Path.Combine("Files", "ZippedAddon.zip"), Path.Combine("FilesTemp", "ZippedAddon.zip")); + + var pathToFile = Path.Combine(Directory.GetCurrentDirectory(), "FilesTemp", "ZippedAddon.zip"); + + var result = await (Task>)_getAddonsFromFilesAsync.Invoke(_installedAddonsProvider, [(object)new List() { pathToFile }])!; + + Assert.Equal(2, result.Count); + + var a = result.First(); + var b = result.Last(); + + Assert.Equal("blood-voxel-pack", a.Key.Id); + Assert.Equal("p292", a.Key.Version); + Assert.Equal("Voxel Pack", a.Value.Title); + + Assert.Equal("blood-voxel-pack-2", b.Key.Id); + Assert.Equal("p292-2", b.Key.Version); + Assert.Equal("Voxel Pack 2", b.Value.Title); + + Assert.True(File.Exists(pathToFile)); + Assert.False(Directory.Exists(pathToFile.Replace(".zip", ""))); + } + + [Fact] + public async Task UnpackedAddonTest() + { + _ = Directory.CreateDirectory("FilesTemp"); + File.Copy(Path.Combine("Files", "UnpackedAddon.zip"), Path.Combine("FilesTemp", "UnpackedAddon.zip")); + + var pathToFile = Path.Combine(Directory.GetCurrentDirectory(), "FilesTemp", "UnpackedAddon.zip"); + + var result = await (Task>)_getAddonsFromFilesAsync.Invoke(_installedAddonsProvider, [(object)new List() { pathToFile }])!; + + Assert.Equal(2, result.Count); + + var a = result.First(); + var b = result.Last(); + + Assert.Equal("blood-voxel-pack", a.Key.Id); + Assert.Equal("p292", a.Key.Version); + Assert.Equal("Voxel Pack", a.Value.Title); + + Assert.Equal("blood-voxel-pack-2", b.Key.Id); + Assert.Equal("p292-2", b.Key.Version); + Assert.Equal("Voxel Pack 2", b.Value.Title); + + Assert.False(File.Exists(pathToFile)); + Assert.True(Directory.Exists(pathToFile.Replace(".zip", ""))); + } + + [Fact] + public async Task LooseMapTest() + { + _ = Directory.CreateDirectory("FilesTemp"); + File.Copy(Path.Combine("Files", "TEST.MAP"), Path.Combine("FilesTemp", "TEST.MAP")); + + var pathToFile = Path.Combine(Directory.GetCurrentDirectory(), "FilesTemp", "TEST.MAP"); + + var result = await (Task>)_getAddonsFromFilesAsync.Invoke(_installedAddonsProvider, [(object)new List() { pathToFile }])!; + + var map = Assert.Single(result); + + Assert.Equal("TEST.MAP", map.Key.Id); + Assert.Null(map.Key.Version); + Assert.Equal("TEST.MAP", map.Value.Title); + + Assert.True(File.Exists(pathToFile)); + } + + [Fact] + public async Task GrpInfoTest() + { + _ = Directory.CreateDirectory("FilesTemp"); + File.Copy(Path.Combine("Files", "GrpInfoAddon.zip"), Path.Combine("FilesTemp", "GrpInfoAddon.zip")); + + var pathToFile = Path.Combine(Directory.GetCurrentDirectory(), "FilesTemp", "GrpInfoAddon.zip"); + + var result = await (Task>)_getAddonsFromFilesAsync.Invoke(_installedAddonsProvider, [(object)new List() { pathToFile }])!; + + Assert.Empty(result); + + Assert.False(File.Exists(pathToFile)); + Assert.True(Directory.Exists(pathToFile.Replace(".zip", ""))); + } +} diff --git a/src/Tests/Files/GrpInfoAddon.zip b/src/Tests/Files/GrpInfoAddon.zip new file mode 100644 index 0000000..125f255 Binary files /dev/null and b/src/Tests/Files/GrpInfoAddon.zip differ diff --git a/src/Tests/Files/TEST.MAP b/src/Tests/Files/TEST.MAP new file mode 100644 index 0000000..4ad2c40 Binary files /dev/null and b/src/Tests/Files/TEST.MAP differ diff --git a/src/Tests/Files/UnpackedAddon.zip b/src/Tests/Files/UnpackedAddon.zip new file mode 100644 index 0000000..60a8af6 Binary files /dev/null and b/src/Tests/Files/UnpackedAddon.zip differ diff --git a/src/Tests/Files/ZippedAddon.zip b/src/Tests/Files/ZippedAddon.zip new file mode 100644 index 0000000..7682626 Binary files /dev/null and b/src/Tests/Files/ZippedAddon.zip differ diff --git a/src/Tests/Tests.csproj b/src/Tests/Tests.csproj index 6594da3..54079d2 100644 --- a/src/Tests/Tests.csproj +++ b/src/Tests/Tests.csproj @@ -6,11 +6,19 @@ BuildLauncher.$(MSBuildProjectName) + + + + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive @@ -27,4 +35,22 @@ + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + + + + PreserveNewest + + +