Add support for mod thumbnails
All checks were successful
Build / Compute Version (push) Successful in 5s
Build / Build Nuget package (push) Successful in 3m39s

This commit is contained in:
2025-06-07 16:31:14 -04:00
parent 825094369f
commit 5f4d306f6c
4 changed files with 142 additions and 37 deletions

View File

@@ -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<IImGuiImageService>();
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<string?> 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<RemoteStorageDownloadUGCResult_t>.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<string?> ThubmnailTask);
private record WhitelistItem(string Id, string? Tooltip, string Author, string? Description);

View File

@@ -20,11 +20,21 @@
<PackageProjectUrl>https://git.zznty.ru/PvE/ClientModLoader</PackageProjectUrl>
<RepositoryUrl>https://git.zznty.ru/PvE/ClientModLoader</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<LangVersion>preview</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="CringePlugins" Version="*" ExcludeAssets="runtime; native"/>
<PackageReference Include="Steamworks.NET" Version="[20.1.0]" ExcludeAssets="runtime; native" />
</ItemGroup>
<Target Name="CopyFiles" AfterTargets="PostBuildEvent">
<PropertyGroup>
<AppdataPath>$([System.Environment]::GetFolderPath(SpecialFolder.ApplicationData))</AppdataPath>
</PropertyGroup>
<ItemGroup>
<OutputFiles Include="$(OutputPath)\*" />
</ItemGroup>
<Copy SourceFiles="@(OutputFiles)" DestinationFolder="$(AppdataPath)\CringeLauncher\plugins\$(ProjectName)" OverwriteReadOnlyFiles="true" />
</Target>
</Project>

View File

@@ -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=="
}
}
}

View File

@@ -1,7 +1,7 @@
{
"sdk": {
"version": "9.0.0",
"version": "10.0.0",
"rollForward": "latestFeature",
"allowPrerelease": false
"allowPrerelease": true
}
}