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 CringePlugins.Abstractions;
using System.Net.Http.Json; using CringePlugins.Services;
using System.Runtime.InteropServices;
using System.Text.Json;
using CringePlugins.Abstractions;
using ImGuiNET; using ImGuiNET;
using Microsoft.Extensions.DependencyInjection;
using Plugin.ClientModLoader.Utils; using Plugin.ClientModLoader.Utils;
using Sandbox;
using Steamworks; using Steamworks;
using System.Collections.Immutable;
using System.Net.Http.Json;
using System.Text.Json;
using VRage; using VRage;
using VRage.FileSystem;
using static ImGuiNET.ImGui; using static ImGuiNET.ImGui;
namespace Plugin.ClientModLoader; namespace Plugin.ClientModLoader;
@@ -15,6 +18,7 @@ public class ModListComponent : IRenderComponent
{ {
private readonly string _configPath; private readonly string _configPath;
private readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web); private readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web);
private readonly IImGuiImageService _imageService = MySandboxGame.Services.GetRequiredService<IImGuiImageService>();
private bool _visible; private bool _visible;
private string _searchQuery = string.Empty; private string _searchQuery = string.Empty;
@@ -167,6 +171,25 @@ public class ModListComponent : IRenderComponent
{ {
Text(_selected.Name); Text(_selected.Name);
Separator(); 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 (BeginTabBar("##ModViewTabs"))
{ {
if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description")) if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description"))
@@ -277,7 +300,7 @@ public class ModListComponent : IRenderComponent
: item.Tooltip, : item.Tooltip,
item.Description, item.Description,
description, $"https://steamcommunity.com/sharedfiles/filedetails/?id={details.m_nPublishedFileId.m_PublishedFileId}", 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; _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) => private static string MapLanguage(MyLanguagesEnum lang) =>
lang switch lang switch
{ {
@@ -314,7 +367,7 @@ public class ModListComponent : IRenderComponent
_ => "english", _ => "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); 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> <PackageProjectUrl>https://git.zznty.ru/PvE/ClientModLoader</PackageProjectUrl>
<RepositoryUrl>https://git.zznty.ru/PvE/ClientModLoader</RepositoryUrl> <RepositoryUrl>https://git.zznty.ru/PvE/ClientModLoader</RepositoryUrl>
<RepositoryType>git</RepositoryType> <RepositoryType>git</RepositoryType>
<LangVersion>preview</LangVersion>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CringePlugins" Version="*" ExcludeAssets="runtime; native"/> <PackageReference Include="CringePlugins" Version="*" ExcludeAssets="runtime; native"/>
<PackageReference Include="Steamworks.NET" Version="[20.1.0]" ExcludeAssets="runtime; native" />
</ItemGroup> </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> </Project>

View File

@@ -5,34 +5,36 @@
"CringePlugins": { "CringePlugins": {
"type": "Direct", "type": "Direct",
"requested": "[*, )", "requested": "[*, )",
"resolved": "0.1.57", "resolved": "0.1.82",
"contentHash": "PR3GGF1qvBMdre3f7CgPBKoHk0/Y8MXFz/Kp9SkAzmJmTzARct0MxFEz+nhUYfoNAma02L5KXuko5QYv3lWmQA==", "contentHash": "PKsCEgA2OoUYElkVUu36ZQ63+ttDXcQmts6r6Im5m/EgbzvRuMVV/n+ew2ZUdJbA3jCFs9wgWDKGTmbfArpddA==",
"dependencies": { "dependencies": {
"ImGui.NET.DirectX": "1.91.0.1", "ImGui.NET.DirectX": "1.91.0.1",
"JsonSchema.Net.Generation": "5.0.2",
"Lib.Harmony.Thin": "2.3.4-torch", "Lib.Harmony.Thin": "2.3.4-torch",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5",
"NLog": "5.4.0", "NLog": "5.4.0",
"NuGet": "0.1.57", "NuGet": "0.1.82",
"SharedCringe": "0.1.57", "SharedCringe": "0.1.82",
"SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30", "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.32",
"Steamworks.NET": "[20.1.0]",
"dnlib": "4.4.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": { "CringeBootstrap.Abstractions": {
"type": "Transitive", "type": "Transitive",
"resolved": "0.1.57", "resolved": "0.1.82",
"contentHash": "0Otka7VBWH8xhkmJ7OsBe0zoZyT8N9W6Bl1ZasymLW5rVkcEwspJt7iZ75mPQOe4qo9UuvnZJdV/fMIYXK2yEg==" "contentHash": "9cN/QbZhF46mdqlUfJgKFE0WIU72kndzAaOfarqmCZ5LOvPRjGLTyEOWmDub9vKvqOKII4txOxIURj7GnPk/0g=="
}, },
"dnlib": { "dnlib": {
"type": "Transitive", "type": "Transitive",
"resolved": "4.4.0", "resolved": "4.4.0",
"contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ==" "contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ=="
}, },
"Humanizer.Core": {
"type": "Transitive",
"resolved": "2.14.1",
"contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
},
"ImGui.NET.DirectX": { "ImGui.NET.DirectX": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.91.0.1", "resolved": "1.91.0.1",
@@ -43,6 +45,37 @@
"System.Runtime.CompilerServices.Unsafe": "6.0.0" "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": { "Lib.Harmony.Thin": {
"type": "Transitive", "type": "Transitive",
"resolved": "2.3.4-torch", "resolved": "2.3.4-torch",
@@ -57,6 +90,11 @@
"resolved": "6.0.0", "resolved": "6.0.0",
"contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg==" "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
}, },
"Microsoft.Extensions.DependencyInjection.Abstractions": {
"type": "Transitive",
"resolved": "9.0.5",
"contentHash": "cjnRtsEAzU73aN6W7vkWy8Phj5t3Xm78HSqgrbh/O4Q9SK/yN73wZVa21QQY6amSLQRQ/M8N+koGnY6PuvKQsw=="
},
"Mono.Cecil": { "Mono.Cecil": {
"type": "Transitive", "type": "Transitive",
"resolved": "0.11.5", "resolved": "0.11.5",
@@ -103,8 +141,8 @@
}, },
"NuGet": { "NuGet": {
"type": "Transitive", "type": "Transitive",
"resolved": "0.1.57", "resolved": "0.1.82",
"contentHash": "7e395oq1nXq61w3G/3dpMZo3XieMynWjgUBZl9B4jbo+08XCu0bPfkAsF793/9GKdVvfflXT0eHVfNziAfnbKg==", "contentHash": "BjixWsaCI+xKpBlUmA8qIsGXQpy9owCC3C93qviKsNCZPjQ5ej+m/DBw5Rarr0InybyBSTHHNVLwDIUtMI5+Aw==",
"dependencies": { "dependencies": {
"NuGet.Frameworks": "6.13.2", "NuGet.Frameworks": "6.13.2",
"NuGet.Versioning": "6.13.2", "NuGet.Versioning": "6.13.2",
@@ -128,12 +166,12 @@
}, },
"SharedCringe": { "SharedCringe": {
"type": "Transitive", "type": "Transitive",
"resolved": "0.1.57", "resolved": "0.1.82",
"contentHash": "Vc6JmpW8R7nVIFz56ItR2uo3kfdc3DQh+ctTw7dqrQgzwUiC0s6j7OOXwSq2nvXBtXtym5E/3Gc3vKsUdhvKPw==", "contentHash": "0t1izvWzkadqvbNJ8/ahmItcgW9ZeNkE+hMQrxYcrUNj7pEd2ZIOdOXdIrsKfDIB/H2Mkw2Zs/rEbIZKc6rvtw==",
"dependencies": { "dependencies": {
"CringeBootstrap.Abstractions": "0.1.57", "CringeBootstrap.Abstractions": "0.1.82",
"NLog": "5.4.0", "NLog": "5.4.0",
"SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30" "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.32"
} }
}, },
"SharpDX": { "SharpDX": {
@@ -143,13 +181,18 @@
}, },
"SpaceEngineersDedicated.ReferenceAssemblies": { "SpaceEngineersDedicated.ReferenceAssemblies": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.206.30", "resolved": "1.206.32",
"contentHash": "xk/EgMhbG7oT4fPzW1DcFT8tYkxJFPK3+j+t4vms9a/wz8cCmszbilA2Y+JWIpmauUDcfovX8eqAOKlgz3dpcg==", "contentHash": "uFhkUUxmumct/turcfMeM2f+jJHxuiB6jAE4JMGa/AOFKCsWIr+ZWTX9hW2muEoJpUNKrzCbGrxH8ssaJUZpig==",
"dependencies": { "dependencies": {
"SharpDX": "4.2.0-keen-cringe", "SharpDX": "4.2.0-keen-cringe",
"protobuf-net": "1.0.0" "protobuf-net": "1.0.0"
} }
}, },
"Steamworks.NET": {
"type": "Transitive",
"resolved": "20.1.0",
"contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ=="
},
"System.Buffers": { "System.Buffers": {
"type": "Transitive", "type": "Transitive",
"resolved": "4.5.1", "resolved": "4.5.1",
@@ -180,12 +223,6 @@
} }
}, },
"net9.0-windows7.0/win-x64": { "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": { "ImGui.NET.DirectX": {
"type": "Transitive", "type": "Transitive",
"resolved": "1.91.0.1", "resolved": "1.91.0.1",
@@ -195,6 +232,11 @@
"System.Numerics.Vectors": "4.5.0", "System.Numerics.Vectors": "4.5.0",
"System.Runtime.CompilerServices.Unsafe": "6.0.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": { "sdk": {
"version": "9.0.0", "version": "10.0.0",
"rollForward": "latestFeature", "rollForward": "latestFeature",
"allowPrerelease": false "allowPrerelease": true
} }
} }