diff --git a/Plugin.ClientModLoader/ModListComponent.cs b/Plugin.ClientModLoader/ModListComponent.cs index 7cf7540..57814bb 100644 --- a/Plugin.ClientModLoader/ModListComponent.cs +++ b/Plugin.ClientModLoader/ModListComponent.cs @@ -1,12 +1,15 @@ -using System.Collections.Immutable; -using System.Net.Http.Json; -using System.Runtime.InteropServices; -using System.Text.Json; -using CringePlugins.Abstractions; +using CringePlugins.Abstractions; +using CringePlugins.Services; using ImGuiNET; +using Microsoft.Extensions.DependencyInjection; using Plugin.ClientModLoader.Utils; +using Sandbox; using Steamworks; +using System.Collections.Immutable; +using System.Net.Http.Json; +using System.Text.Json; using VRage; +using VRage.FileSystem; using static ImGuiNET.ImGui; namespace Plugin.ClientModLoader; @@ -15,6 +18,7 @@ public class ModListComponent : IRenderComponent { private readonly string _configPath; private readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web); + private readonly IImGuiImageService _imageService = MySandboxGame.Services.GetRequiredService(); private bool _visible; private string _searchQuery = string.Empty; @@ -167,6 +171,25 @@ public class ModListComponent : IRenderComponent { Text(_selected.Name); Separator(); + + if (_selected.ThubmnailTask.IsCompletedSuccessfully && _selected.ThubmnailTask.Result is { } thumbnail) + { + var img = _imageService.GetFromPath(thumbnail); + + var size = img.Size; + + if (size.X > 256 || size.Y > 256) + { + //scale down to fit + var scale = Math.Min(256f / size.X, 256f / size.Y); + size = new(size.X * scale, size.Y * scale); + } + + Image(img, size); + } + + + if (BeginTabBar("##ModViewTabs")) { if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description")) @@ -277,7 +300,7 @@ public class ModListComponent : IRenderComponent : item.Tooltip, item.Description, description, $"https://steamcommunity.com/sharedfiles/filedetails/?id={details.m_nPublishedFileId.m_PublishedFileId}", - details.m_rtimeCreated, details.m_rtimeUpdated, item.Author)); + details.m_rtimeCreated, details.m_rtimeUpdated, item.Author, GetThumbnailImageAsync(details.m_hPreviewFile))); } _modList = list; @@ -288,6 +311,36 @@ public class ModListComponent : IRenderComponent } } + private static async Task GetThumbnailImageAsync(UGCHandle_t handle) + { + var dir = MyFileSystem.WorkshopBrowserPath; + + if (!Directory.Exists(dir)) + Directory.CreateDirectory(dir); + + var path = Path.Join(dir, $"{handle.m_UGCHandle}.png"); + + if (File.Exists(path)) + { + if (File.GetLastWriteTimeUtc(path) + TimeSpan.FromMinutes(10) < DateTime.UtcNow) + File.Delete(path); + else + return path; + } + + var call = SteamRemoteStorage.UGCDownloadToLocation(handle, path, 0); + + var result = await CallResultAsync.Create(call); + + if (result.m_eResult != EResult.k_EResultOK || result.m_hFile != handle || !File.Exists(path)) + { + return null; + } + + File.SetLastWriteTimeUtc(path, DateTime.UtcNow); + return path; + } + private static string MapLanguage(MyLanguagesEnum lang) => lang switch { @@ -314,7 +367,7 @@ public class ModListComponent : IRenderComponent _ => "english", }; - private record ModItem(ulong Id, string Name, string Summary, string? Description, string ModDescription, string Url, long Created, long Updated, string Author); + private record ModItem(ulong Id, string Name, string Summary, string? Description, string ModDescription, string Url, long Created, long Updated, string Author, Task ThubmnailTask); private record WhitelistItem(string Id, string? Tooltip, string Author, string? Description); diff --git a/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj b/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj index 9119d57..97b0b49 100644 --- a/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj +++ b/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj @@ -20,11 +20,21 @@ https://git.zznty.ru/PvE/ClientModLoader https://git.zznty.ru/PvE/ClientModLoader git + preview - + + + $([System.Environment]::GetFolderPath(SpecialFolder.ApplicationData)) + + + + + + + diff --git a/Plugin.ClientModLoader/packages.lock.json b/Plugin.ClientModLoader/packages.lock.json index 083802f..8759c2f 100644 --- a/Plugin.ClientModLoader/packages.lock.json +++ b/Plugin.ClientModLoader/packages.lock.json @@ -5,34 +5,36 @@ "CringePlugins": { "type": "Direct", "requested": "[*, )", - "resolved": "0.1.57", - "contentHash": "PR3GGF1qvBMdre3f7CgPBKoHk0/Y8MXFz/Kp9SkAzmJmTzARct0MxFEz+nhUYfoNAma02L5KXuko5QYv3lWmQA==", + "resolved": "0.1.82", + "contentHash": "PKsCEgA2OoUYElkVUu36ZQ63+ttDXcQmts6r6Im5m/EgbzvRuMVV/n+ew2ZUdJbA3jCFs9wgWDKGTmbfArpddA==", "dependencies": { "ImGui.NET.DirectX": "1.91.0.1", + "JsonSchema.Net.Generation": "5.0.2", "Lib.Harmony.Thin": "2.3.4-torch", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", "NLog": "5.4.0", - "NuGet": "0.1.57", - "SharedCringe": "0.1.57", - "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30", + "NuGet": "0.1.82", + "SharedCringe": "0.1.82", + "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.32", + "Steamworks.NET": "[20.1.0]", "dnlib": "4.4.0" } }, - "Steamworks.NET": { - "type": "Direct", - "requested": "[20.1.0, 20.1.0]", - "resolved": "20.1.0", - "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" - }, "CringeBootstrap.Abstractions": { "type": "Transitive", - "resolved": "0.1.57", - "contentHash": "0Otka7VBWH8xhkmJ7OsBe0zoZyT8N9W6Bl1ZasymLW5rVkcEwspJt7iZ75mPQOe4qo9UuvnZJdV/fMIYXK2yEg==" + "resolved": "0.1.82", + "contentHash": "9cN/QbZhF46mdqlUfJgKFE0WIU72kndzAaOfarqmCZ5LOvPRjGLTyEOWmDub9vKvqOKII4txOxIURj7GnPk/0g==" }, "dnlib": { "type": "Transitive", "resolved": "4.4.0", "contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ==" }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.14.1", + "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==" + }, "ImGui.NET.DirectX": { "type": "Transitive", "resolved": "1.91.0.1", @@ -43,6 +45,37 @@ "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, + "Json.More.Net": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "ZXAKl2VsdnIZeUo1PFII3Oi1m1L4YQjEyDjygHfHln5vgsjgIo749X6xWkv7qFYp8RROES+vOEfDcvvoVgs8kA==" + }, + "JsonPointer.Net": { + "type": "Transitive", + "resolved": "5.3.1", + "contentHash": "3e2OJjU0OaE26XC/klgxbJuXvteFWTDJIJv0ITYWcJEoskq7jzUwPSC1s0iz4wPPQnfN7vwwFmg2gJfwRAPwgw==", + "dependencies": { + "Humanizer.Core": "2.14.1", + "Json.More.Net": "2.1.1" + } + }, + "JsonSchema.Net": { + "type": "Transitive", + "resolved": "7.3.4", + "contentHash": "7GggWrdzKrtGWETRn3dcMnmuLSyWaDkBK94TK80LEHQEVz4bmsQc7FYO7qL40RDdZU2YPz5d98aT9lW5OYExuA==", + "dependencies": { + "JsonPointer.Net": "5.3.1" + } + }, + "JsonSchema.Net.Generation": { + "type": "Transitive", + "resolved": "5.0.2", + "contentHash": "+khIPgLqOyFOWjgHSzXMjJijwbQb85/cFRf4NwTaV6QBoGM9IT8LeLCnmwazruwKsx16HB1UFX3mslUujfjVpg==", + "dependencies": { + "Humanizer.Core": "2.14.1", + "JsonSchema.Net": "7.3.4" + } + }, "Lib.Harmony.Thin": { "type": "Transitive", "resolved": "2.3.4-torch", @@ -57,6 +90,11 @@ "resolved": "6.0.0", "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "cjnRtsEAzU73aN6W7vkWy8Phj5t3Xm78HSqgrbh/O4Q9SK/yN73wZVa21QQY6amSLQRQ/M8N+koGnY6PuvKQsw==" + }, "Mono.Cecil": { "type": "Transitive", "resolved": "0.11.5", @@ -103,8 +141,8 @@ }, "NuGet": { "type": "Transitive", - "resolved": "0.1.57", - "contentHash": "7e395oq1nXq61w3G/3dpMZo3XieMynWjgUBZl9B4jbo+08XCu0bPfkAsF793/9GKdVvfflXT0eHVfNziAfnbKg==", + "resolved": "0.1.82", + "contentHash": "BjixWsaCI+xKpBlUmA8qIsGXQpy9owCC3C93qviKsNCZPjQ5ej+m/DBw5Rarr0InybyBSTHHNVLwDIUtMI5+Aw==", "dependencies": { "NuGet.Frameworks": "6.13.2", "NuGet.Versioning": "6.13.2", @@ -128,12 +166,12 @@ }, "SharedCringe": { "type": "Transitive", - "resolved": "0.1.57", - "contentHash": "Vc6JmpW8R7nVIFz56ItR2uo3kfdc3DQh+ctTw7dqrQgzwUiC0s6j7OOXwSq2nvXBtXtym5E/3Gc3vKsUdhvKPw==", + "resolved": "0.1.82", + "contentHash": "0t1izvWzkadqvbNJ8/ahmItcgW9ZeNkE+hMQrxYcrUNj7pEd2ZIOdOXdIrsKfDIB/H2Mkw2Zs/rEbIZKc6rvtw==", "dependencies": { - "CringeBootstrap.Abstractions": "0.1.57", + "CringeBootstrap.Abstractions": "0.1.82", "NLog": "5.4.0", - "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30" + "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.32" } }, "SharpDX": { @@ -143,13 +181,18 @@ }, "SpaceEngineersDedicated.ReferenceAssemblies": { "type": "Transitive", - "resolved": "1.206.30", - "contentHash": "xk/EgMhbG7oT4fPzW1DcFT8tYkxJFPK3+j+t4vms9a/wz8cCmszbilA2Y+JWIpmauUDcfovX8eqAOKlgz3dpcg==", + "resolved": "1.206.32", + "contentHash": "uFhkUUxmumct/turcfMeM2f+jJHxuiB6jAE4JMGa/AOFKCsWIr+ZWTX9hW2muEoJpUNKrzCbGrxH8ssaJUZpig==", "dependencies": { "SharpDX": "4.2.0-keen-cringe", "protobuf-net": "1.0.0" } }, + "Steamworks.NET": { + "type": "Transitive", + "resolved": "20.1.0", + "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" + }, "System.Buffers": { "type": "Transitive", "resolved": "4.5.1", @@ -180,12 +223,6 @@ } }, "net9.0-windows7.0/win-x64": { - "Steamworks.NET": { - "type": "Direct", - "requested": "[20.1.0, 20.1.0]", - "resolved": "20.1.0", - "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" - }, "ImGui.NET.DirectX": { "type": "Transitive", "resolved": "1.91.0.1", @@ -195,6 +232,11 @@ "System.Numerics.Vectors": "4.5.0", "System.Runtime.CompilerServices.Unsafe": "6.0.0" } + }, + "Steamworks.NET": { + "type": "Transitive", + "resolved": "20.1.0", + "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" } } } diff --git a/global.json b/global.json index 90b3042..999059c 100644 --- a/global.json +++ b/global.json @@ -1,7 +1,7 @@ { "sdk": { - "version": "9.0.0", + "version": "10.0.0", "rollForward": "latestFeature", - "allowPrerelease": false + "allowPrerelease": true } } \ No newline at end of file