From 947fcde9ca72e0d08fa8d4815943186ba96c7d03 Mon Sep 17 00:00:00 2001
From: zznty <94796179+zznty@users.noreply.github.com>
Date: Sun, 11 May 2025 02:37:57 +0700
Subject: [PATCH] 1
---
.gitignore | 5 +
.../.idea/.gitignore | 13 +
.../.idea/encodings.xml | 4 +
.../.idea/git_toolbox_blame.xml | 6 +
.../.idea/indexLayout.xml | 8 +
.../.idea/vcs.xml | 6 +
Plugin.ClientModLoader.sln.DotSettings.user | 13 +
Plugin.ClientModLoader.slnx | 3 +
Plugin.ClientModLoader/ModInjector.cs | 87 +++++
Plugin.ClientModLoader/ModListComponent.cs | 321 ++++++++++++++++++
.../Plugin.ClientModLoader.csproj | 21 ++
Plugin.ClientModLoader/Plugin.cs | 34 ++
.../Utils/CallResultAsync.cs | 32 ++
Plugin.ClientModLoader/packages.lock.json | 201 +++++++++++
14 files changed, 754 insertions(+)
create mode 100644 .gitignore
create mode 100644 .idea/.idea.Plugin.ClientModLoader/.idea/.gitignore
create mode 100644 .idea/.idea.Plugin.ClientModLoader/.idea/encodings.xml
create mode 100644 .idea/.idea.Plugin.ClientModLoader/.idea/git_toolbox_blame.xml
create mode 100644 .idea/.idea.Plugin.ClientModLoader/.idea/indexLayout.xml
create mode 100644 .idea/.idea.Plugin.ClientModLoader/.idea/vcs.xml
create mode 100644 Plugin.ClientModLoader.sln.DotSettings.user
create mode 100644 Plugin.ClientModLoader.slnx
create mode 100644 Plugin.ClientModLoader/ModInjector.cs
create mode 100644 Plugin.ClientModLoader/ModListComponent.cs
create mode 100644 Plugin.ClientModLoader/Plugin.ClientModLoader.csproj
create mode 100644 Plugin.ClientModLoader/Plugin.cs
create mode 100644 Plugin.ClientModLoader/Utils/CallResultAsync.cs
create mode 100644 Plugin.ClientModLoader/packages.lock.json
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..add57be
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,5 @@
+bin/
+obj/
+/packages/
+riderModule.iml
+/_ReSharper.Caches/
\ No newline at end of file
diff --git a/.idea/.idea.Plugin.ClientModLoader/.idea/.gitignore b/.idea/.idea.Plugin.ClientModLoader/.idea/.gitignore
new file mode 100644
index 0000000..bf3cc9e
--- /dev/null
+++ b/.idea/.idea.Plugin.ClientModLoader/.idea/.gitignore
@@ -0,0 +1,13 @@
+# Default ignored files
+/shelf/
+/workspace.xml
+# Rider ignored files
+/projectSettingsUpdater.xml
+/modules.xml
+/contentModel.xml
+/.idea.Plugin.ClientModLoader.iml
+# Editor-based HTTP Client requests
+/httpRequests/
+# Datasource local storage ignored files
+/dataSources/
+/dataSources.local.xml
diff --git a/.idea/.idea.Plugin.ClientModLoader/.idea/encodings.xml b/.idea/.idea.Plugin.ClientModLoader/.idea/encodings.xml
new file mode 100644
index 0000000..df87cf9
--- /dev/null
+++ b/.idea/.idea.Plugin.ClientModLoader/.idea/encodings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Plugin.ClientModLoader/.idea/git_toolbox_blame.xml b/.idea/.idea.Plugin.ClientModLoader/.idea/git_toolbox_blame.xml
new file mode 100644
index 0000000..7dc1249
--- /dev/null
+++ b/.idea/.idea.Plugin.ClientModLoader/.idea/git_toolbox_blame.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Plugin.ClientModLoader/.idea/indexLayout.xml b/.idea/.idea.Plugin.ClientModLoader/.idea/indexLayout.xml
new file mode 100644
index 0000000..7b08163
--- /dev/null
+++ b/.idea/.idea.Plugin.ClientModLoader/.idea/indexLayout.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/.idea.Plugin.ClientModLoader/.idea/vcs.xml b/.idea/.idea.Plugin.ClientModLoader/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/.idea.Plugin.ClientModLoader/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Plugin.ClientModLoader.sln.DotSettings.user b/Plugin.ClientModLoader.sln.DotSettings.user
new file mode 100644
index 0000000..688a97f
--- /dev/null
+++ b/Plugin.ClientModLoader.sln.DotSettings.user
@@ -0,0 +1,13 @@
+
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
+ ForceIncluded
\ No newline at end of file
diff --git a/Plugin.ClientModLoader.slnx b/Plugin.ClientModLoader.slnx
new file mode 100644
index 0000000..c34b7c4
--- /dev/null
+++ b/Plugin.ClientModLoader.slnx
@@ -0,0 +1,3 @@
+
+
+
diff --git a/Plugin.ClientModLoader/ModInjector.cs b/Plugin.ClientModLoader/ModInjector.cs
new file mode 100644
index 0000000..7a12da6
--- /dev/null
+++ b/Plugin.ClientModLoader/ModInjector.cs
@@ -0,0 +1,87 @@
+using System.Reflection.Emit;
+using System.Runtime.CompilerServices;
+using HarmonyLib;
+using Sandbox.Definitions;
+using Sandbox.Engine.Networking;
+using Sandbox.Game.World;
+using VRage.Game;
+
+namespace Plugin.ClientModLoader;
+
+[HarmonyPatch]
+internal static class ModInjector
+{
+ public static HashSet Mods = [];
+ private static readonly List AdditionalFilledModItems = [];
+
+ [HarmonyPatch(typeof(MyWorkshop), nameof(MyWorkshop.DownloadWorldModsBlockingInternal))]
+ [HarmonyPrefix]
+ private static void DownloadModsBlockingPrefix(ref List mods, ref List __state)
+ {
+ AdditionalFilledModItems.Clear();
+ __state = mods;
+ AppendToList(ref mods);
+ }
+
+ [HarmonyPatch(typeof(MyWorkshop), nameof(MyWorkshop.DownloadWorldModsBlockingInternal))]
+ [HarmonyPostfix]
+ private static void DownloadModsBlockingPostfix(List mods, List __state)
+ {
+ foreach (var mod in mods)
+ {
+ var index = __state.FindIndex(b =>
+ b.PublishedFileId == mod.PublishedFileId && b.PublishedServiceName == mod.PublishedServiceName);
+
+ if (index != -1)
+ {
+ var stateMod = __state[index];
+ stateMod.SetModData(mod.GetModData());
+ __state[index] = stateMod;
+ }
+ else if (Mods.Contains(mod.PublishedFileId))
+ AdditionalFilledModItems.Add(mod);
+ else
+ __state.Add(mod);
+ }
+ }
+
+ [HarmonyPatch(typeof(MyDefinitionManager), nameof(MyDefinitionManager.LoadData))]
+ [HarmonyPrefix]
+ private static void LoadDefinitionsPrefix(ref List mods) => AppendToList(ref mods);
+
+ [HarmonyPatch(typeof(MyScriptManager), nameof(MyScriptManager.LoadData))]
+ [HarmonyTranspiler]
+ private static IEnumerable LoadScriptsTranspiler(IEnumerable instructions, ILGenerator generator)
+ {
+ var staticGetter = AccessTools.PropertyGetter(typeof(MySession), nameof(MySession.Static));
+ var modsGetter = AccessTools.PropertyGetter(typeof(MySession), nameof(MySession.Mods));
+ return new CodeMatcher(instructions, generator)
+ .Start()
+ .DeclareLocal(typeof(List), out var modsLocal)
+ .CreateLabel(out var start)
+ .InsertAndAdvance(
+ new(OpCodes.Call, staticGetter),
+ new(OpCodes.Call, modsGetter),
+ new(OpCodes.Stloc, modsLocal),
+ new(OpCodes.Ldloc, modsLocal),
+ new(OpCodes.Brfalse, start),
+ new(OpCodes.Ldloca, modsLocal),
+ CodeInstruction.Call(typeof(ModInjector), nameof(AppendToList))
+ )
+ .MatchStartForward(CodeMatch.Calls(staticGetter), CodeMatch.Calls(modsGetter))
+ .Repeat(a => a
+ .SetAndAdvance(OpCodes.Ldloc, modsLocal)
+ .SetAndAdvance(OpCodes.Nop, null))
+ .Instructions();
+ }
+
+ private static void AppendToList(ref List mods)
+ {
+ // copy
+ mods = mods.ToList();
+
+ mods.AddRange(AdditionalFilledModItems.Count > 0
+ ? AdditionalFilledModItems
+ : Mods.Select(mod => new MyObjectBuilder_Checkpoint.ModItem(mod, "Steam")));
+ }
+}
\ No newline at end of file
diff --git a/Plugin.ClientModLoader/ModListComponent.cs b/Plugin.ClientModLoader/ModListComponent.cs
new file mode 100644
index 0000000..25dc673
--- /dev/null
+++ b/Plugin.ClientModLoader/ModListComponent.cs
@@ -0,0 +1,321 @@
+using System.Collections.Immutable;
+using System.Net.Http.Json;
+using System.Runtime.InteropServices;
+using System.Text.Json;
+using CringePlugins.Abstractions;
+using ImGuiNET;
+using Plugin.ClientModLoader.Utils;
+using Steamworks;
+using VRage;
+using static ImGuiNET.ImGui;
+
+namespace Plugin.ClientModLoader;
+
+public class ModListComponent : IRenderComponent
+{
+ private readonly string _configPath;
+ private readonly JsonSerializerOptions _options = new(JsonSerializerDefaults.Web);
+
+ private bool _visible;
+ private string _searchQuery = string.Empty;
+ private Task? _searchTask;
+
+ private PublishedFileId_t[] _mods = [];
+ private ImmutableDictionary _whitelist = ImmutableDictionary.Empty;
+
+ private List _modList = [];
+ private ModItem? _selected;
+ public HashSet Installed { get; }
+
+ public bool Visible
+ {
+ get => _visible;
+ set => _visible = value;
+ }
+
+ public ModListComponent(string configPath)
+ {
+ _configPath = configPath;
+ if (File.Exists(configPath))
+ {
+ using var stream = File.OpenRead(configPath);
+ Installed = JsonSerializer.Deserialize>(stream, _options)!;
+ }
+ else Installed = [];
+
+ _searchTask = DownloadWhitelist();
+ }
+
+ private async Task DownloadWhitelist()
+ {
+ using var client = new HttpClient();
+ var response =
+ await client.GetFromJsonAsync(
+ "https://github.com/sepluginloader/sepluginloader.github.io/raw/refs/heads/main/plugins.json");
+
+ if (response is null) return;
+
+ var mods = new List();
+ var builder = ImmutableDictionary.CreateBuilder();
+
+ foreach (var item in response.Mods)
+ {
+ if (!ulong.TryParse(item.Id, out var id)) continue;
+
+ mods.Add(new PublishedFileId_t(id));
+ builder.Add(id, item);
+ }
+
+ _mods = mods.ToArray();
+ _whitelist = builder.ToImmutable();
+ await RefreshAsync();
+ }
+
+ public void OnFrame()
+ {
+ if (!Visible) return;
+ SetNextWindowSize(new(700, 500), ImGuiCond.FirstUseEver);
+ if (!Begin("Mod List", ref _visible)) return;
+
+ try
+ {
+ InputText("##searchbox", ref _searchQuery, 256);
+
+ SameLine();
+
+ if (Button("Search"))
+ {
+ _searchTask = RefreshAsync();
+ return;
+ }
+
+ Spacing();
+
+ switch (_searchTask)
+ {
+ case { IsCompleted: false }:
+ TextDisabled("Loading...");
+ return;
+ case { IsCompletedSuccessfully: false }:
+ {
+ TextDisabled("Failed to load plugins list");
+ if (_searchTask.Exception is null) return;
+
+ foreach (var exception in _searchTask.Exception.InnerExceptions)
+ {
+ TextWrapped($"{exception.GetType()}: {exception.Message}");
+ }
+
+ return;
+ }
+ }
+
+ if (_modList.Count == 0)
+ {
+ TextDisabled("Nothing found");
+ return;
+ }
+
+ BeginChild("List", new(400, 0), ImGuiChildFlags.Border | ImGuiChildFlags.ResizeX);
+ {
+ if (BeginTable("AvailableModsTable", 3,
+ ImGuiTableFlags.ScrollY | ImGuiTableFlags.Resizable | ImGuiTableFlags.SizingStretchProp))
+ {
+ TableSetupColumn("Name", ImGuiTableColumnFlags.None, .75f);
+ TableSetupColumn("Installed", ImGuiTableColumnFlags.None, .25f);
+ TableHeadersRow();
+
+ foreach (var mod in _modList)
+ {
+ TableNextRow();
+
+ TableNextColumn();
+
+ var selected = _selected == mod;
+
+ if (Selectable(mod.Name, ref selected, ImGuiSelectableFlags.SpanAllColumns))
+ {
+ _selected = selected ? mod : null;
+ }
+
+ if (!string.IsNullOrEmpty(mod.Summary) && IsItemHovered(ImGuiHoveredFlags.ForTooltip))
+ {
+ SetTooltip(mod.Summary);
+ }
+
+ TableNextColumn();
+
+ var installed = Installed.Contains(mod.Id);
+ TextColored(installed ? new(0f, 1f, 0f, 1f) : new(1f, 0f, 0f, 1f),
+ installed ? "Installed" : "Not Installed");
+ }
+
+ EndTable();
+ }
+
+ EndChild();
+ }
+
+ SameLine();
+
+ BeginGroup();
+
+ BeginChild("Mod View", new(0, -GetFrameHeightWithSpacing())); // Leave room for 1 line below us
+
+ if (_selected is not null)
+ {
+ Text(_selected.Name);
+ Separator();
+ if (BeginTabBar("##ModViewTabs"))
+ {
+ if (!string.IsNullOrEmpty(_selected.Description) && BeginTabItem("Description"))
+ {
+ TextWrapped(_selected.Description);
+ EndTabItem();
+ }
+
+ if (BeginTabItem("Mod Description"))
+ {
+ TextWrapped(string.IsNullOrEmpty(_selected.ModDescription) ? "Nothing." : _selected.ModDescription);
+ EndTabItem();
+ }
+
+ if (BeginTabItem("Details"))
+ {
+ TextLinkOpenURL("Mod URL", _selected.Url);
+
+ Text("Author:");
+ SameLine();
+ TextWrapped(_selected.Author);
+
+ Text("Created:");
+ SameLine();
+ TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Created).ToString("g"));
+
+ Text("Updated:");
+ SameLine();
+ TextWrapped(DateTimeOffset.FromUnixTimeSeconds(_selected.Updated).ToString("g"));
+
+ EndTabItem();
+ }
+
+ EndTabBar();
+ }
+ }
+
+ EndChild();
+
+ if (_selected is not null)
+ {
+ var installed = Installed.Contains(_selected.Id);
+ if (Button(installed ? "Uninstall" : "Install"))
+ {
+ if (installed)
+ Installed.Remove(_selected.Id);
+ else
+ Installed.Add(_selected.Id);
+
+ Save();
+ }
+ }
+
+ EndGroup();
+ }
+ finally
+ {
+ End();
+ }
+ }
+
+
+ private void Save()
+ {
+ using var stream = File.Create(_configPath);
+
+ JsonSerializer.Serialize(stream, Installed, _options);
+ }
+
+ private async Task RefreshAsync()
+ {
+ var handle = SteamUGC.CreateQueryUGCDetailsRequest(_mods, (uint)_mods.Length);
+
+ if (handle.m_UGCQueryHandle == ulong.MaxValue)
+ throw new Exception("Failed to create UGC request");
+
+ try
+ {
+ SteamUGC.SetSearchText(handle, _searchQuery);
+ SteamUGC.SetReturnLongDescription(handle, true);
+ // TODO font support for other languages
+ // SteamUGC.SetLanguage(handle, MapLanguage(MySandboxGame.Config.Language));
+
+ var call = SteamUGC.SendQueryUGCRequest(handle);
+
+ var result = await CallResultAsync.Create(call);
+
+ var list = new List((int)result.m_unNumResultsReturned);
+
+ for (uint i = 0; i < result.m_unNumResultsReturned; i++)
+ {
+ if (!SteamUGC.GetQueryUGCResult(handle, i, out var details))
+ break;
+ if (details.m_eResult != EResult.k_EResultOK)
+ continue;
+
+ var title = details.m_rgchTitle;
+
+ if (!string.IsNullOrEmpty(_searchQuery) && !title.Contains(_searchQuery, StringComparison.OrdinalIgnoreCase))
+ continue;
+
+ var item = _whitelist[details.m_nPublishedFileId.m_PublishedFileId];
+
+ var description = details.m_rgchDescription;
+ list.Add(new(details.m_nPublishedFileId.m_PublishedFileId, title,
+ string.IsNullOrEmpty(item.Tooltip)
+ ? description[..Math.Min(description.Length - 1, 255)]
+ : item.Tooltip,
+ item.Description,
+ description, $"https://steamcommunity.com/sharedfiles/filedetails/?id={details.m_nPublishedFileId.m_PublishedFileId}",
+ details.m_rtimeCreated, details.m_rtimeUpdated, item.Author));
+ }
+
+ _modList = list;
+ }
+ finally
+ {
+ SteamUGC.ReleaseQueryUGCRequest(handle);
+ }
+ }
+
+ private static string MapLanguage(MyLanguagesEnum lang) =>
+ lang switch
+ {
+ MyLanguagesEnum.Czech => "czech",
+ MyLanguagesEnum.German => "german",
+ MyLanguagesEnum.Russian => "russian",
+ MyLanguagesEnum.Spanish_Spain => "spanish",
+ MyLanguagesEnum.French => "french",
+ MyLanguagesEnum.Italian => "italian",
+ MyLanguagesEnum.Danish => "danish",
+ MyLanguagesEnum.Dutch => "dutch",
+ MyLanguagesEnum.Polish => "polish",
+ MyLanguagesEnum.Finnish => "finnish",
+ MyLanguagesEnum.Hungarian => "hungarian",
+ MyLanguagesEnum.Portuguese_Brazil => "brazilian",
+ MyLanguagesEnum.Norwegian => "norwegian",
+ MyLanguagesEnum.Spanish_HispanicAmerica => "latam",
+ MyLanguagesEnum.Swedish => "swedish",
+ MyLanguagesEnum.Romanian => "romanian",
+ MyLanguagesEnum.Ukrainian => "ukrainian",
+ MyLanguagesEnum.Turkish => "turkish",
+ MyLanguagesEnum.ChineseChina => "schinese",
+ MyLanguagesEnum.Japanese => "japanese",
+ _ => "english",
+ };
+
+ private record ModItem(ulong Id, string Name, string Summary, string? Description, string ModDescription, string Url, long Created, long Updated, string Author);
+
+ private record WhitelistItem(string Id, string? Tooltip, string Author, string? Description);
+
+ private record Whitelist(ImmutableArray Mods);
+}
\ No newline at end of file
diff --git a/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj b/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj
new file mode 100644
index 0000000..95bbe6f
--- /dev/null
+++ b/Plugin.ClientModLoader/Plugin.ClientModLoader.csproj
@@ -0,0 +1,21 @@
+
+
+
+ net9.0-windows
+ enable
+ enable
+ win-x64
+ True
+ true
+ true
+ true
+ https://ng.zznty.ru/v3/index.json
+ true
+
+
+
+
+
+
+
+
diff --git a/Plugin.ClientModLoader/Plugin.cs b/Plugin.ClientModLoader/Plugin.cs
new file mode 100644
index 0000000..04d5746
--- /dev/null
+++ b/Plugin.ClientModLoader/Plugin.cs
@@ -0,0 +1,34 @@
+using CringePlugins.Render;
+using HarmonyLib;
+using VRage.Plugins;
+
+namespace Plugin.ClientModLoader;
+
+public class Plugin : IPlugin
+{
+ private ModListComponent? _component;
+
+ private readonly DirectoryInfo _dir =
+ new(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
+ "CringeLauncher"));
+
+ public void Dispose()
+ {
+ }
+
+ public void Init(object gameInstance)
+ {
+ new Harmony("Plugin.ClientModLoader").PatchAll(typeof(Plugin).Assembly);
+ RenderHandler.Current.RegisterComponent(_component = new ModListComponent(Path.Join(_dir.FullName, "mods.json")));
+ ModInjector.Mods = _component.Installed;
+ }
+
+ public void Update()
+ {
+ }
+
+ public void OpenConfigDialog()
+ {
+ if (_component != null) _component.Visible = true;
+ }
+}
\ No newline at end of file
diff --git a/Plugin.ClientModLoader/Utils/CallResultAsync.cs b/Plugin.ClientModLoader/Utils/CallResultAsync.cs
new file mode 100644
index 0000000..a9e20bd
--- /dev/null
+++ b/Plugin.ClientModLoader/Utils/CallResultAsync.cs
@@ -0,0 +1,32 @@
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+using Steamworks;
+
+namespace Plugin.ClientModLoader.Utils;
+
+public static class CallResultAsync where T : struct
+{
+ public static async Task Create(SteamAPICall_t call)
+ {
+ var tcs = new TaskCompletionSource();
+ using var callResult = CallResult.Create((args, failed) =>
+ {
+ if (failed)
+ {
+ ref var result = ref Unsafe.As(ref args);
+ tcs.TrySetException(new Exception($"CallResult failed: {result.m_eResult}"));
+ }
+ else tcs.TrySetResult(args);
+ });
+ callResult.Set(call);
+
+ return await tcs.Task;
+ }
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8)]
+ private struct GenericCallResult
+ {
+ public UGCQueryHandle_t m_handle;
+ public EResult m_eResult;
+ }
+}
\ No newline at end of file
diff --git a/Plugin.ClientModLoader/packages.lock.json b/Plugin.ClientModLoader/packages.lock.json
new file mode 100644
index 0000000..a993fb3
--- /dev/null
+++ b/Plugin.ClientModLoader/packages.lock.json
@@ -0,0 +1,201 @@
+{
+ "version": 1,
+ "dependencies": {
+ "net9.0-windows7.0": {
+ "CringePlugins": {
+ "type": "Direct",
+ "requested": "[*, )",
+ "resolved": "0.1.51",
+ "contentHash": "6v6FfWlrLge3E67R75P/svFtvbAodzffwMyISUYFrZK6XTYsLPLExegnHswPNMC1PFbwD5ukhXYF9eUgIluubQ==",
+ "dependencies": {
+ "ImGui.NET.DirectX": "1.91.0.1",
+ "Lib.Harmony.Thin": "2.3.4-torch",
+ "NLog": "5.4.0",
+ "NuGet": "0.1.51",
+ "SharedCringe": "0.1.51",
+ "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30",
+ "dnlib": "4.4.0"
+ }
+ },
+ "Steamworks.NET": {
+ "type": "Direct",
+ "requested": "[20.1.0, )",
+ "resolved": "20.1.0",
+ "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ=="
+ },
+ "CringeBootstrap.Abstractions": {
+ "type": "Transitive",
+ "resolved": "0.1.51",
+ "contentHash": "dpA0Tr7Ir+6WzlVq98on0kxcEwpUr/arl0+8EX3QPsO2tXYTuRJRDMqy4SlMjN5t+xDfT/iILzkcUldIfogE8A=="
+ },
+ "dnlib": {
+ "type": "Transitive",
+ "resolved": "4.4.0",
+ "contentHash": "cKHI720q+zfEEvzklWVGt6B0TH3AibAyJbpUJl4U6KvTP13tycfnqJpkGHRZ/oQ45BTIoIxIwltHIJVDN+iCqQ=="
+ },
+ "ImGui.NET.DirectX": {
+ "type": "Transitive",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ },
+ "Lib.Harmony.Thin": {
+ "type": "Transitive",
+ "resolved": "2.3.4-torch",
+ "contentHash": "UnLUnLLiXfHZdKa1zhi6w8cl8tJTrpVixLtvjFEVtlDA6Rkf06OcZ2gSidcbcgKjTcR+fk5Qsdos3mU5oohzfg==",
+ "dependencies": {
+ "MonoMod.Core": "1.2.2",
+ "System.Text.Json": "9.0.0"
+ }
+ },
+ "Microsoft.Bcl.AsyncInterfaces": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "UcSjPsst+DfAdJGVDsu346FX0ci0ah+lw3WRtn18NUwEqRt70HaOQ7lI72vy3+1LxtqI3T5GWwV39rQSrCzAeg=="
+ },
+ "Mono.Cecil": {
+ "type": "Transitive",
+ "resolved": "0.11.5",
+ "contentHash": "fxfX+0JGTZ8YQeu1MYjbBiK2CYTSzDyEeIixt+yqKKTn7FW8rv7JMY70qevup4ZJfD7Kk/VG/jDzQQTpfch87g=="
+ },
+ "MonoMod.Backports": {
+ "type": "Transitive",
+ "resolved": "1.1.2",
+ "contentHash": "baYlNy8n8kmaNhNvqmZ/dIPOeO1r9//dG1i2WbunMWtWZ2EKtIgmXaS+ZzphzTsikkGnoD4Jwr5g0TVdpDjgpw==",
+ "dependencies": {
+ "MonoMod.ILHelpers": "1.1.0"
+ }
+ },
+ "MonoMod.Core": {
+ "type": "Transitive",
+ "resolved": "1.2.2",
+ "contentHash": "3R9mQ7TxeQQBFLtGTR2VIDSBGx/I7d8RYpxvW1Mot0/PB6+UOnHr+lkw7dj8cus8YSnLdCFT+CG4JW89daEvjg==",
+ "dependencies": {
+ "Mono.Cecil": "0.11.5",
+ "MonoMod.Backports": "1.1.2",
+ "MonoMod.ILHelpers": "1.1.0",
+ "MonoMod.Utils": "25.0.8"
+ }
+ },
+ "MonoMod.ILHelpers": {
+ "type": "Transitive",
+ "resolved": "1.1.0",
+ "contentHash": "L2FWjhTrv7tcIxshfZ+M3OcaNr4cNw0IwiVZEgwqRnZ5QAN3+RrNJ8ZwCzwXUWyPDqooJxMcjjg8PsSYUiNBjQ=="
+ },
+ "MonoMod.Utils": {
+ "type": "Transitive",
+ "resolved": "25.0.8",
+ "contentHash": "8wfyawgvGqUvfchAj7/gPazAjXO8CWNyXH+C0az+hgJH/80zVL5LxDhQMz0NQTyoCEJWU6gNBGc7CL+G7vCbaQ==",
+ "dependencies": {
+ "Mono.Cecil": "0.11.5",
+ "MonoMod.Backports": "1.1.2",
+ "MonoMod.ILHelpers": "1.1.0"
+ }
+ },
+ "NLog": {
+ "type": "Transitive",
+ "resolved": "5.4.0",
+ "contentHash": "LwMcGSW3soF3/SL68rlJN3Eh3ktrAPycC3zZR/07OYBPraZUu0bygEC7kIN10lUQgMXT4s84Fi1chglGdGrQEg=="
+ },
+ "NuGet": {
+ "type": "Transitive",
+ "resolved": "0.1.51",
+ "contentHash": "fwUsNKy/EQB26JocU3suqYqFqbQ8mb63Ri5NGf7OPy7zLooxHNUYaN+MuBhbshveP+8IKdlPfc8UkrFyzKK8PA==",
+ "dependencies": {
+ "NuGet.Frameworks": "6.13.2",
+ "NuGet.Versioning": "6.13.2",
+ "System.Linq.Async": "6.0.1"
+ }
+ },
+ "NuGet.Frameworks": {
+ "type": "Transitive",
+ "resolved": "6.13.2",
+ "contentHash": "SQKUf56j7IdJL//fU7fcmn234awjRA2qLvgbfs/TxmY7oJrNOxaaDxASyCbS4eJW3LCOd6ONHMZ/cPlbQh4xVg=="
+ },
+ "NuGet.Versioning": {
+ "type": "Transitive",
+ "resolved": "6.13.2",
+ "contentHash": "pGYNyvCVM+Z9jITTiJiuxFC8oJXFdh2k25ZDV4tSAOSuKyAWvh1VcfJy0WZGWdI6J7Avkbl0qra7XENYFSy4Ng=="
+ },
+ "protobuf-net": {
+ "type": "Transitive",
+ "resolved": "1.0.0",
+ "contentHash": "kTGOK0E87473sOImOjgZOnz3kTC2aMLffoRWQLYNuBLJnwNNmjanF9IkevZ9Q7yYLeABQfcF3BpeepuMntMVNw=="
+ },
+ "SharedCringe": {
+ "type": "Transitive",
+ "resolved": "0.1.51",
+ "contentHash": "9QargvU/hAVUXt1QZaeCHExmoYfrtHP9Vq9X5oMbIX8lOCmjulZx0rSuwoDR46/I1eu4+xVvM78/u+F4UiP6uw==",
+ "dependencies": {
+ "CringeBootstrap.Abstractions": "0.1.51",
+ "NLog": "5.4.0",
+ "SpaceEngineersDedicated.ReferenceAssemblies": "1.206.30"
+ }
+ },
+ "SharpDX": {
+ "type": "Transitive",
+ "resolved": "4.2.0-keen-cringe",
+ "contentHash": "LaJN3h1Gi1FWVdef2I5WtOH9gwzKCBniH0CragarbkN2QheYY6Lqm+91PcOfp1w/4wdVb+k8Kjv3sO393Tphtw=="
+ },
+ "SpaceEngineersDedicated.ReferenceAssemblies": {
+ "type": "Transitive",
+ "resolved": "1.206.30",
+ "contentHash": "xk/EgMhbG7oT4fPzW1DcFT8tYkxJFPK3+j+t4vms9a/wz8cCmszbilA2Y+JWIpmauUDcfovX8eqAOKlgz3dpcg==",
+ "dependencies": {
+ "SharpDX": "4.2.0-keen-cringe",
+ "protobuf-net": "1.0.0"
+ }
+ },
+ "System.Buffers": {
+ "type": "Transitive",
+ "resolved": "4.5.1",
+ "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg=="
+ },
+ "System.Linq.Async": {
+ "type": "Transitive",
+ "resolved": "6.0.1",
+ "contentHash": "0YhHcaroWpQ9UCot3Pizah7ryAzQhNvobLMSxeDIGmnXfkQn8u5owvpOH0K6EVB+z9L7u6Cc4W17Br/+jyttEQ==",
+ "dependencies": {
+ "Microsoft.Bcl.AsyncInterfaces": "6.0.0"
+ }
+ },
+ "System.Numerics.Vectors": {
+ "type": "Transitive",
+ "resolved": "4.5.0",
+ "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.0.0",
+ "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg=="
+ },
+ "System.Text.Json": {
+ "type": "Transitive",
+ "resolved": "9.0.0",
+ "contentHash": "js7+qAu/9mQvnhA4EfGMZNEzXtJCDxgkgj8ohuxq/Qxv+R56G+ljefhiJHOxTNiw54q8vmABCWUwkMulNdlZ4A=="
+ }
+ },
+ "net9.0-windows7.0/win-x64": {
+ "Steamworks.NET": {
+ "type": "Direct",
+ "requested": "[20.1.0, )",
+ "resolved": "20.1.0",
+ "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ=="
+ },
+ "ImGui.NET.DirectX": {
+ "type": "Transitive",
+ "resolved": "1.91.0.1",
+ "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==",
+ "dependencies": {
+ "System.Buffers": "4.5.1",
+ "System.Numerics.Vectors": "4.5.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.0.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file