From eba25bbf887b67bacf85556d587951bbd9e9253c Mon Sep 17 00:00:00 2001 From: zznty <94796179+zznty@users.noreply.github.com> Date: Mon, 2 Jun 2025 22:40:16 +0700 Subject: [PATCH] config handler global service provider with our stuff so we stop using statics everywhere polly retry policy for httpclient --- CringeBootstrap/packages.lock.json | 300 ++++++++++-------- CringeLauncher/CringeLauncher.csproj | 2 + CringeLauncher/Launcher.cs | 41 ++- CringeLauncher/packages.lock.json | 300 ++++++++++-------- CringePlugins/Config/ConfigHandler.cs | 151 +++++++++ .../Config/Spec/IConfigurationSpecProvider.cs | 21 ++ CringePlugins/CringePlugins.csproj | 2 + CringePlugins/Loader/PluginsLifetime.cs | 37 +-- .../Services/GameServicesExtension.cs | 13 + CringePlugins/Ui/PluginListComponent.cs | 56 ++-- CringePlugins/packages.lock.json | 91 +++--- NuGet/NuGetClient.cs | 43 +-- NuGet/PackageSourceMapping.cs | 4 +- global.json | 4 +- 14 files changed, 670 insertions(+), 395 deletions(-) create mode 100644 CringePlugins/Config/ConfigHandler.cs create mode 100644 CringePlugins/Config/Spec/IConfigurationSpecProvider.cs create mode 100644 CringePlugins/Services/GameServicesExtension.cs diff --git a/CringeBootstrap/packages.lock.json b/CringeBootstrap/packages.lock.json index 9e8d188..be094bb 100644 --- a/CringeBootstrap/packages.lock.json +++ b/CringeBootstrap/packages.lock.json @@ -31,14 +31,45 @@ "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", - "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==", + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" + }, + "Json.More.Net": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "ZXAKl2VsdnIZeUo1PFII3Oi1m1L4YQjEyDjygHfHln5vgsjgIo749X6xWkv7qFYp8RROES+vOEfDcvvoVgs8kA==" + }, + "JsonPointer.Net": { + "type": "Transitive", + "resolved": "5.3.1", + "contentHash": "3e2OJjU0OaE26XC/klgxbJuXvteFWTDJIJv0ITYWcJEoskq7jzUwPSC1s0iz4wPPQnfN7vwwFmg2gJfwRAPwgw==", "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "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": { @@ -46,8 +77,7 @@ "resolved": "2.3.4-torch", "contentHash": "UnLUnLLiXfHZdKa1zhi6w8cl8tJTrpVixLtvjFEVtlDA6Rkf06OcZ2gSidcbcgKjTcR+fk5Qsdos3mU5oohzfg==", "dependencies": { - "MonoMod.Core": "1.2.2", - "System.Text.Json": "9.0.0" + "MonoMod.Core": "1.2.2" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -65,9 +95,7 @@ "resolved": "4.13.0", "contentHash": "T8nRl4mAUY4mhdYM4U2ra2vP2EL+ol8Yqwo0gwC/V55vmlXq9NxdIkZJynTpTL1uX/jHijJ90AeOEx4lf7OwzQ==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.11.0", - "System.Collections.Immutable": "8.0.0", - "System.Reflection.Metadata": "8.0.0" + "Microsoft.CodeAnalysis.Analyzers": "3.11.0" } }, "Microsoft.CodeAnalysis.CSharp": { @@ -76,22 +104,105 @@ "contentHash": "BsH7Vijbj9IL7Fj4k/ysZSVyLGFqr75wmdFGwCKWJvSjnA1xwPaQ3hkB2BQdHOt5CpEYA6Q0I6Oo5sDTDHqHsg==", "dependencies": { "Microsoft.CodeAnalysis.Analyzers": "3.11.0", - "Microsoft.CodeAnalysis.Common": "[4.13.0]", - "System.Collections.Immutable": "8.0.0", - "System.Reflection.Metadata": "8.0.0" + "Microsoft.CodeAnalysis.Common": "[4.13.0]" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "uYXLg2Gt8KUH5nT3u+TBpg9VrRcN5+2zPmIjqEHR4kOoBwsbtMDncEJw9HiLvZqGgIo2TR4oraibAoy5hXn2bQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "ew0G6gIznnyAkbIa67wXspkDFcVektjN3xaDAfBDIPbWph+rbuGaaohFxUSGw28ht7wdcWtTtElKnzfkcDDbOQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "7pQ4Tkyofm8DFWFhqn9ZmG8qSAC2VitWleATj5qob9V9KtoxCVdwRtmiVl/ha3WAgjkEfW++JLWXox9MJwMgkg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "N1Mn0T/tUBPoLL+Fzsp+VCEtneUhhxc1//Dx3BeuQ8AX+XrMlYCfnp2zgpEXnTCB7053CLdiqVWPZ7mEX6MPjg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" + "resolved": "9.0.5", + "contentHash": "cjnRtsEAzU73aN6W7vkWy8Phj5t3Xm78HSqgrbh/O4Q9SK/yN73wZVa21QQY6amSLQRQ/M8N+koGnY6PuvKQsw==" + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "fRiUjmhm9e4vMp6WEO9MgWNxVtWSr4Pcgh1W4DyJIr8bRANlZz9JU7uicf7ShzMspDxo/9Ejo9zJ6qQZY0IhVw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "9.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "6YfTcULCYREMTqtk+s3UiszsFV2xN2FXtxdQpurmQJY9Cp/QGiM4MTKfJKUo7AzdLuzjOKKMWjQITmvtK7AsUg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "6vbo3XjyEc+w/kv/Dkfv9NA7iSdIdX5dlU9Shk3wJJ0fiZpCVzVW5FJtNoIePX5hS0ENNpHPClq/qtq06yM4FQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Diagnostics": "9.0.5", + "Microsoft.Extensions.Logging": "9.0.5", + "Microsoft.Extensions.Logging.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } + }, + "Microsoft.Extensions.Http.Polly": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "VCFPTik1LjPuUiS3vHy65UUzffm7MKGG6tBTFOrDklGDT36BsB9srrW+otYVT7nw6a/NbE8SM4kKsPzuRWxLRA==", + "dependencies": { + "Microsoft.Extensions.Http": "9.0.5", + "Polly": "7.2.4", + "Polly.Extensions.Http": "3.0.0" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "rQU61lrgvpE/UgcAd4E56HPxUIkX/VUQCxWmwDTLLVeuwRDYTL0q/FLGfAW17cGTKyCh7ywYAEnY3sTEvURsfg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "9.0.5", + "Microsoft.Extensions.Logging.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "resolved": "9.0.5", + "contentHash": "pP1PADCrIxMYJXxFmTVbAgEU7GVpjK5i0/tyfU9DiE0oXQy3JWQaOVgCkrCiePLgS8b5sghM3Fau3EeHiVWbCg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5" } }, "Microsoft.Extensions.ObjectPool": { @@ -99,6 +210,32 @@ "resolved": "5.0.10", "contentHash": "pp9tbGqIhdEXL6Q1yJl+zevAJSq4BsxqhS1GXzBvEsEz9DDNu9GLNzgUy2xyFc4YjB4m4Ff2YEWTnvQvVYdkvQ==" }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "vPdJQU8YLOUSSK8NL0RmwcXJr2E0w8xH559PGQl4JYsglgilZr9LZnqV2zdgk+XR05+kuvhBEZKoDVd46o7NqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "CJbAVdovKPFh2FoKxesu20odRVSbL/vtvzzObnG+5u38sOfzRS2Ncy25id0TjYUGQzMhNnJUHgTUzTMDl/3c9g==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Configuration.Binder": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "b4OAv1qE1C9aM+ShWJu3rlo/WjDwa/I30aIPXqDWSKXTtKl1Wwh6BZn+glH5HndGVVn3C6ZAPQj5nv7/7HJNBQ==" + }, "Mono.Cecil": { "type": "Transitive", "resolved": "0.11.5", @@ -153,6 +290,19 @@ "resolved": "6.13.2", "contentHash": "pGYNyvCVM+Z9jITTiJiuxFC8oJXFdh2k25ZDV4tSAOSuKyAWvh1VcfJy0WZGWdI6J7Avkbl0qra7XENYFSy4Ng==" }, + "Polly": { + "type": "Transitive", + "resolved": "7.2.4", + "contentHash": "bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==" + }, + "Polly.Extensions.Http": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", + "dependencies": { + "Polly": "7.1.0" + } + }, "protobuf-net": { "type": "Transitive", "resolved": "1.0.0", @@ -166,15 +316,12 @@ "SixLabors.Core": { "type": "Transitive", "resolved": "1.0.0-beta0007", - "contentHash": "s9aPl6yxwcvoKRD0u0zjkCISZCCifbUi9/XVFjdvlx5Pt7vRYmGV0anq1EEftUjIEHbEu5aNBipbUSBIV2CE7w==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.1" - } + "contentHash": "s9aPl6yxwcvoKRD0u0zjkCISZCCifbUi9/XVFjdvlx5Pt7vRYmGV0anq1EEftUjIEHbEu5aNBipbUSBIV2CE7w==" }, "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" @@ -185,21 +332,11 @@ "resolved": "20.1.0", "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, "System.CodeDom": { "type": "Transitive", "resolved": "9.0.4", "contentHash": "aJdv7Z87PoPW8ijvGIincocooYRbH3Umtlz7OrJKf6GDInbdu1bvk5X1fFlmbl7WP+9ntoIBd7NjKz+siVFdHA==" }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==" - }, "System.Configuration.ConfigurationManager": { "type": "Transitive", "resolved": "9.0.4", @@ -222,11 +359,6 @@ "System.Configuration.ConfigurationManager": "9.0.4" } }, - "System.Formats.Asn1": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" - }, "System.Linq.Async": { "type": "Transitive", "resolved": "6.0.1", @@ -243,53 +375,13 @@ "System.CodeDom": "9.0.4" } }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, "System.Private.ServiceModel": { "type": "Transitive", "resolved": "4.10.3", "contentHash": "BcUV7OERlLqGxDXZuIyIMMmk1PbqBblLRbAoigmzIUx/M8A+8epvyPyXRpbgoucKH7QmfYdQIev04Phx2Co08A==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "Microsoft.Extensions.ObjectPool": "5.0.10", - "System.Numerics.Vectors": "4.5.0", - "System.Reflection.DispatchProxy": "4.7.1", - "System.Security.Cryptography.Xml": "6.0.1", - "System.Security.Principal.Windows": "5.0.0" - } - }, - "System.Reflection.DispatchProxy": { - "type": "Transitive", - "resolved": "4.7.1", - "contentHash": "C1sMLwIG6ILQ2bmOT4gh62V6oJlyF4BlHcVMrOoor49p0Ji2tA8QAoqyMcIhAdH6OHKJ8m7BU+r4LK2CUEOKqw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==", - "dependencies": { - "System.Collections.Immutable": "8.0.0" - } - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" - }, - "System.Security.Cryptography.Pkcs": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "ynmbW2GjIGg9K1wXmVIRs4IlyDolf0JXNpzFQ8JCVgwM+myUC2JeUggl2PwQig2PNVMegKmN1aAx7WPQ8tI3vA==", - "dependencies": { - "System.Formats.Asn1": "6.0.0" + "Microsoft.Extensions.ObjectPool": "5.0.10" } }, "System.Security.Cryptography.ProtectedData": { @@ -297,32 +389,12 @@ "resolved": "9.0.4", "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ==" }, - "System.Security.Cryptography.Xml": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "5e5bI28T0x73AwTsbuFP4qSRzthmU2C0Gqgg3AZ3KTxmSyA+Uhk31puA3srdaeWaacVnHhLdJywCzqOiEpbO/w==", - "dependencies": { - "System.Security.AccessControl": "6.0.0", - "System.Security.Cryptography.Pkcs": "6.0.1" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, - "System.Text.Json": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "js7+qAu/9mQvnhA4EfGMZNEzXtJCDxgkgj8ohuxq/Qxv+R56G+ljefhiJHOxTNiw54q8vmABCWUwkMulNdlZ4A==" - }, "Torch.SixLabors.ImageSharp": { "type": "Transitive", "resolved": "1.0.0-beta6", "contentHash": "WJ7ocT79HgmuKi0+ltpvXTiMI80UcI3DeS8XSfYwJtTB1tcQws6zLPGuUwra6qe6qRrFfpABeDP3xvHV1rJgfg==", "dependencies": { - "SixLabors.Core": "1.0.0-beta0007", - "System.Runtime.CompilerServices.Unsafe": "4.5.1" + "SixLabors.Core": "1.0.0-beta0007" } }, "cringebootstrap.abstractions": { @@ -335,6 +407,8 @@ "CringeBootstrap.Abstractions": "[1.0.0, )", "CringePlugins": "[1.0.0, )", "Microsoft.CodeAnalysis.CSharp": "[4.13.0, )", + "Microsoft.Extensions.DependencyInjection": "[9.0.5, )", + "Microsoft.Extensions.Http.Polly": "[9.0.5, )", "NLog": "[5.4.0, )", "SpaceEngineersDedicated.ReferenceAssemblies": "[1.*, )", "System.Diagnostics.PerformanceCounter": "[9.0.4, )", @@ -349,6 +423,7 @@ "type": "Project", "dependencies": { "ImGui.NET.DirectX": "[1.91.0.1, )", + "JsonSchema.Net.Generation": "[5.0.2, )", "Lib.Harmony.Thin": "[2.3.4-torch, )", "NLog": "[5.4.0, )", "NuGet": "[1.0.0, )", @@ -379,12 +454,7 @@ "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" - } + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" }, "Steamworks.NET": { "type": "Transitive", @@ -411,24 +481,6 @@ "dependencies": { "System.CodeDom": "9.0.4" } - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" - }, - "System.Security.Cryptography.Pkcs": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "ynmbW2GjIGg9K1wXmVIRs4IlyDolf0JXNpzFQ8JCVgwM+myUC2JeUggl2PwQig2PNVMegKmN1aAx7WPQ8tI3vA==", - "dependencies": { - "System.Formats.Asn1": "6.0.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" } } } diff --git a/CringeLauncher/CringeLauncher.csproj b/CringeLauncher/CringeLauncher.csproj index 3b03008..602312f 100644 --- a/CringeLauncher/CringeLauncher.csproj +++ b/CringeLauncher/CringeLauncher.csproj @@ -29,11 +29,13 @@ all runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/CringeLauncher/Launcher.cs b/CringeLauncher/Launcher.cs index a950b0b..62d24eb 100644 --- a/CringeLauncher/Launcher.cs +++ b/CringeLauncher/Launcher.cs @@ -1,14 +1,20 @@ -using System.Reflection; +using System.Diagnostics.CodeAnalysis; +using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Loader; using CringeBootstrap.Abstractions; using CringeLauncher.Utils; +using CringePlugins.Config; using CringePlugins.Loader; using CringePlugins.Render; +using CringePlugins.Services; using CringePlugins.Splash; using HarmonyLib; +using Microsoft.Extensions.DependencyInjection; using NLog; +using Polly; +using Polly.Extensions.Http; using Sandbox; using Sandbox.Engine.Networking; using Sandbox.Engine.Platform.VideoMode; @@ -78,10 +84,15 @@ public class Launcher : ICorePlugin _harmony.PatchAll(typeof(Launcher).Assembly); + MyFileSystem.ExePath = Path.GetDirectoryName(args.ElementAtOrDefault(0) ?? Assembly.GetExecutingAssembly().Location)!; + MyFileSystem.RootPath = new DirectoryInfo(MyFileSystem.ExePath).Parent!.FullName; + var splash = new Splash(); - - splash.DefineStage(_lifetime = new PluginsLifetime(Path.GetDirectoryName(args[0])!)); - + + var serviceProvider = SetupServices(); + + splash.DefineStage(_lifetime = serviceProvider.GetRequiredService()); + InitTexts(); SpaceEngineersGame.SetupBasicGameInfo(); MyFinalBuildConstants.APP_VERSION = MyPerGameSettings.BasicGameInfo.GameVersion.GetValueOrDefault(); @@ -99,8 +110,6 @@ public class Launcher : ICorePlugin MyPlatformGameSettings.SIMPLIFIED_SIMULATION_OVERRIDE = false; } - MyFileSystem.ExePath = Path.GetDirectoryName(args.ElementAtOrDefault(0) ?? Assembly.GetExecutingAssembly().Location)!; - MyFileSystem.RootPath = new DirectoryInfo(MyFileSystem.ExePath).Parent!.FullName; MyInitializer.InvokeBeforeRun(AppId, MyPerGameSettings.BasicGameInfo.ApplicationName, MyVRage.Platform.System.GetRootPath(), MyVRage.Platform.System.GetAppDataPath(),true, 3, () => { @@ -142,11 +151,29 @@ public class Launcher : ICorePlugin public void Run() => _game?.Run(); + + private static IServiceProvider SetupServices() + { + var services = new ServiceCollection(); + + services.AddHttpClient() + .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler + { + AutomaticDecompression = System.Net.DecompressionMethods.All + }) + .AddPolicyHandler(HttpPolicyExtensions.HandleTransientHttpError().WaitAndRetryAsync(5, _ => TimeSpan.FromSeconds(1))); + + services.AddSingleton(_ => RenderHandler.Current) + .AddSingleton(_ => new ConfigHandler(Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher", "config")))); + + return GameServicesExtension.GameServices = services.BuildServiceProvider(); + } + private void WaitForDevice() { if (_renderComponent!.RenderThread.CurrentSettings.DRSSettingsPresets is not null) return; - + var resetEvent = new ManualResetEventSlim(false); void RenderThreadOnSizeChanged(int width, int height, MyViewport viewport) diff --git a/CringeLauncher/packages.lock.json b/CringeLauncher/packages.lock.json index f36cf41..0f95c9c 100644 --- a/CringeLauncher/packages.lock.json +++ b/CringeLauncher/packages.lock.json @@ -30,9 +30,27 @@ "contentHash": "BsH7Vijbj9IL7Fj4k/ysZSVyLGFqr75wmdFGwCKWJvSjnA1xwPaQ3hkB2BQdHOt5CpEYA6Q0I6Oo5sDTDHqHsg==", "dependencies": { "Microsoft.CodeAnalysis.Analyzers": "3.11.0", - "Microsoft.CodeAnalysis.Common": "[4.13.0]", - "System.Collections.Immutable": "8.0.0", - "System.Reflection.Metadata": "8.0.0" + "Microsoft.CodeAnalysis.Common": "[4.13.0]" + } + }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Direct", + "requested": "[9.0.5, )", + "resolved": "9.0.5", + "contentHash": "N1Mn0T/tUBPoLL+Fzsp+VCEtneUhhxc1//Dx3BeuQ8AX+XrMlYCfnp2zgpEXnTCB7053CLdiqVWPZ7mEX6MPjg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5" + } + }, + "Microsoft.Extensions.Http.Polly": { + "type": "Direct", + "requested": "[9.0.5, )", + "resolved": "9.0.5", + "contentHash": "VCFPTik1LjPuUiS3vHy65UUzffm7MKGG6tBTFOrDklGDT36BsB9srrW+otYVT7nw6a/NbE8SM4kKsPzuRWxLRA==", + "dependencies": { + "Microsoft.Extensions.Http": "9.0.5", + "Polly": "7.2.4", + "Polly.Extensions.Http": "3.0.0" } }, "Microsoft.Windows.CsWin32": { @@ -55,8 +73,8 @@ "SpaceEngineersDedicated.ReferenceAssemblies": { "type": "Direct", "requested": "[1.*, )", - "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" @@ -87,11 +105,7 @@ "contentHash": "BcUV7OERlLqGxDXZuIyIMMmk1PbqBblLRbAoigmzIUx/M8A+8epvyPyXRpbgoucKH7QmfYdQIev04Phx2Co08A==", "dependencies": { "Microsoft.Bcl.AsyncInterfaces": "5.0.0", - "Microsoft.Extensions.ObjectPool": "5.0.10", - "System.Numerics.Vectors": "4.5.0", - "System.Reflection.DispatchProxy": "4.7.1", - "System.Security.Cryptography.Xml": "6.0.1", - "System.Security.Principal.Windows": "5.0.0" + "Microsoft.Extensions.ObjectPool": "5.0.10" } }, "Torch.SixLabors.ImageSharp": { @@ -100,8 +114,7 @@ "resolved": "1.0.0-beta6", "contentHash": "WJ7ocT79HgmuKi0+ltpvXTiMI80UcI3DeS8XSfYwJtTB1tcQws6zLPGuUwra6qe6qRrFfpABeDP3xvHV1rJgfg==", "dependencies": { - "SixLabors.Core": "1.0.0-beta0007", - "System.Runtime.CompilerServices.Unsafe": "4.5.1" + "SixLabors.Core": "1.0.0-beta0007" } }, "Velopack": { @@ -114,14 +127,45 @@ "NuGet.Versioning": "6.12.1" } }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.14.1", + "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==" + }, "ImGui.NET.DirectX": { "type": "Transitive", "resolved": "1.91.0.1", - "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==", + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" + }, + "Json.More.Net": { + "type": "Transitive", + "resolved": "2.1.1", + "contentHash": "ZXAKl2VsdnIZeUo1PFII3Oi1m1L4YQjEyDjygHfHln5vgsjgIo749X6xWkv7qFYp8RROES+vOEfDcvvoVgs8kA==" + }, + "JsonPointer.Net": { + "type": "Transitive", + "resolved": "5.3.1", + "contentHash": "3e2OJjU0OaE26XC/klgxbJuXvteFWTDJIJv0ITYWcJEoskq7jzUwPSC1s0iz4wPPQnfN7vwwFmg2gJfwRAPwgw==", "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "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": { @@ -129,8 +173,7 @@ "resolved": "2.3.4-torch", "contentHash": "UnLUnLLiXfHZdKa1zhi6w8cl8tJTrpVixLtvjFEVtlDA6Rkf06OcZ2gSidcbcgKjTcR+fk5Qsdos3mU5oohzfg==", "dependencies": { - "MonoMod.Core": "1.2.2", - "System.Text.Json": "9.0.0" + "MonoMod.Core": "1.2.2" } }, "Microsoft.Bcl.AsyncInterfaces": { @@ -148,22 +191,87 @@ "resolved": "4.13.0", "contentHash": "T8nRl4mAUY4mhdYM4U2ra2vP2EL+ol8Yqwo0gwC/V55vmlXq9NxdIkZJynTpTL1uX/jHijJ90AeOEx4lf7OwzQ==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.11.0", - "System.Collections.Immutable": "8.0.0", - "System.Reflection.Metadata": "8.0.0" + "Microsoft.CodeAnalysis.Analyzers": "3.11.0" + } + }, + "Microsoft.Extensions.Configuration": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "uYXLg2Gt8KUH5nT3u+TBpg9VrRcN5+2zPmIjqEHR4kOoBwsbtMDncEJw9HiLvZqGgIo2TR4oraibAoy5hXn2bQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Configuration.Abstractions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "ew0G6gIznnyAkbIa67wXspkDFcVektjN3xaDAfBDIPbWph+rbuGaaohFxUSGw28ht7wdcWtTtElKnzfkcDDbOQ==", + "dependencies": { + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Configuration.Binder": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "7pQ4Tkyofm8DFWFhqn9ZmG8qSAC2VitWleATj5qob9V9KtoxCVdwRtmiVl/ha3WAgjkEfW++JLWXox9MJwMgkg==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5" } }, "Microsoft.Extensions.DependencyInjection.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "cjWrLkJXK0rs4zofsK4bSdg+jhDLTaxrkXu4gS6Y7MAlCvRyNNgwY/lJi5RDlQOnSZweHqoyvgvbdvQsRIW+hg==" + "resolved": "9.0.5", + "contentHash": "cjnRtsEAzU73aN6W7vkWy8Phj5t3Xm78HSqgrbh/O4Q9SK/yN73wZVa21QQY6amSLQRQ/M8N+koGnY6PuvKQsw==" + }, + "Microsoft.Extensions.Diagnostics": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "fRiUjmhm9e4vMp6WEO9MgWNxVtWSr4Pcgh1W4DyJIr8bRANlZz9JU7uicf7ShzMspDxo/9Ejo9zJ6qQZY0IhVw==", + "dependencies": { + "Microsoft.Extensions.Configuration": "9.0.5", + "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.5", + "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.5" + } + }, + "Microsoft.Extensions.Diagnostics.Abstractions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "6YfTcULCYREMTqtk+s3UiszsFV2xN2FXtxdQpurmQJY9Cp/QGiM4MTKfJKUo7AzdLuzjOKKMWjQITmvtK7AsUg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } + }, + "Microsoft.Extensions.Http": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "6vbo3XjyEc+w/kv/Dkfv9NA7iSdIdX5dlU9Shk3wJJ0fiZpCVzVW5FJtNoIePX5hS0ENNpHPClq/qtq06yM4FQ==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Diagnostics": "9.0.5", + "Microsoft.Extensions.Logging": "9.0.5", + "Microsoft.Extensions.Logging.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } + }, + "Microsoft.Extensions.Logging": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "rQU61lrgvpE/UgcAd4E56HPxUIkX/VUQCxWmwDTLLVeuwRDYTL0q/FLGfAW17cGTKyCh7ywYAEnY3sTEvURsfg==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection": "9.0.5", + "Microsoft.Extensions.Logging.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5" + } }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "arDBqTgFCyS0EvRV7O3MZturChstm50OJ0y9bDJvAcmEPJm0FFpFyjU/JLYyStNGGey081DvnQYlncNX5SJJGA==", + "resolved": "9.0.5", + "contentHash": "pP1PADCrIxMYJXxFmTVbAgEU7GVpjK5i0/tyfU9DiE0oXQy3JWQaOVgCkrCiePLgS8b5sghM3Fau3EeHiVWbCg==", "dependencies": { - "Microsoft.Extensions.DependencyInjection.Abstractions": "8.0.0" + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5" } }, "Microsoft.Extensions.ObjectPool": { @@ -171,6 +279,32 @@ "resolved": "5.0.10", "contentHash": "pp9tbGqIhdEXL6Q1yJl+zevAJSq4BsxqhS1GXzBvEsEz9DDNu9GLNzgUy2xyFc4YjB4m4Ff2YEWTnvQvVYdkvQ==" }, + "Microsoft.Extensions.Options": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "vPdJQU8YLOUSSK8NL0RmwcXJr2E0w8xH559PGQl4JYsglgilZr9LZnqV2zdgk+XR05+kuvhBEZKoDVd46o7NqA==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Options.ConfigurationExtensions": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "CJbAVdovKPFh2FoKxesu20odRVSbL/vtvzzObnG+5u38sOfzRS2Ncy25id0TjYUGQzMhNnJUHgTUzTMDl/3c9g==", + "dependencies": { + "Microsoft.Extensions.Configuration.Abstractions": "9.0.5", + "Microsoft.Extensions.Configuration.Binder": "9.0.5", + "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.5", + "Microsoft.Extensions.Options": "9.0.5", + "Microsoft.Extensions.Primitives": "9.0.5" + } + }, + "Microsoft.Extensions.Primitives": { + "type": "Transitive", + "resolved": "9.0.5", + "contentHash": "b4OAv1qE1C9aM+ShWJu3rlo/WjDwa/I30aIPXqDWSKXTtKl1Wwh6BZn+glH5HndGVVn3C6ZAPQj5nv7/7HJNBQ==" + }, "Microsoft.Windows.SDK.Win32Docs": { "type": "Transitive", "resolved": "0.1.42-alpha", @@ -238,6 +372,19 @@ "resolved": "6.13.2", "contentHash": "pGYNyvCVM+Z9jITTiJiuxFC8oJXFdh2k25ZDV4tSAOSuKyAWvh1VcfJy0WZGWdI6J7Avkbl0qra7XENYFSy4Ng==" }, + "Polly": { + "type": "Transitive", + "resolved": "7.2.4", + "contentHash": "bw00Ck5sh6ekduDE3mnCo1ohzuad946uslCDEENu3091+6UKnBuKLo4e+yaNcCzXxOZCXWY2gV4a35+K1d4LDA==" + }, + "Polly.Extensions.Http": { + "type": "Transitive", + "resolved": "3.0.0", + "contentHash": "drrG+hB3pYFY7w1c3BD+lSGYvH2oIclH8GRSehgfyP5kjnFnHKQuuBhuHLv+PWyFuaTDyk/vfRpnxOzd11+J8g==", + "dependencies": { + "Polly": "7.1.0" + } + }, "protobuf-net": { "type": "Transitive", "resolved": "1.0.0", @@ -251,31 +398,18 @@ "SixLabors.Core": { "type": "Transitive", "resolved": "1.0.0-beta0007", - "contentHash": "s9aPl6yxwcvoKRD0u0zjkCISZCCifbUi9/XVFjdvlx5Pt7vRYmGV0anq1EEftUjIEHbEu5aNBipbUSBIV2CE7w==", - "dependencies": { - "System.Runtime.CompilerServices.Unsafe": "4.5.1" - } + "contentHash": "s9aPl6yxwcvoKRD0u0zjkCISZCCifbUi9/XVFjdvlx5Pt7vRYmGV0anq1EEftUjIEHbEu5aNBipbUSBIV2CE7w==" }, "Steamworks.NET": { "type": "Transitive", "resolved": "20.1.0", "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, "System.CodeDom": { "type": "Transitive", "resolved": "9.0.4", "contentHash": "aJdv7Z87PoPW8ijvGIincocooYRbH3Umtlz7OrJKf6GDInbdu1bvk5X1fFlmbl7WP+9ntoIBd7NjKz+siVFdHA==" }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==" - }, "System.Configuration.ConfigurationManager": { "type": "Transitive", "resolved": "9.0.4", @@ -290,11 +424,6 @@ "resolved": "9.0.4", "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ==" }, - "System.Formats.Asn1": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "T6fD00dQ3NTbPDy31m4eQUwKW84s03z0N2C8HpOklyeaDgaJPa/TexP4/SkORMSOwc7WhKifnA6Ya33AkzmafA==" - }, "System.Linq.Async": { "type": "Transitive", "resolved": "6.0.1", @@ -303,66 +432,11 @@ "Microsoft.Bcl.AsyncInterfaces": "6.0.0" } }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, - "System.Reflection.DispatchProxy": { - "type": "Transitive", - "resolved": "4.7.1", - "contentHash": "C1sMLwIG6ILQ2bmOT4gh62V6oJlyF4BlHcVMrOoor49p0Ji2tA8QAoqyMcIhAdH6OHKJ8m7BU+r4LK2CUEOKqw==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==", - "dependencies": { - "System.Collections.Immutable": "8.0.0" - } - }, - "System.Runtime.CompilerServices.Unsafe": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" - }, - "System.Security.Cryptography.Pkcs": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "ynmbW2GjIGg9K1wXmVIRs4IlyDolf0JXNpzFQ8JCVgwM+myUC2JeUggl2PwQig2PNVMegKmN1aAx7WPQ8tI3vA==", - "dependencies": { - "System.Formats.Asn1": "6.0.0" - } - }, "System.Security.Cryptography.ProtectedData": { "type": "Transitive", "resolved": "9.0.4", "contentHash": "o94k2RKuAce3GeDMlUvIXlhVa1kWpJw95E6C9LwW0KlG0nj5+SgCiIxJ2Eroqb9sLtG1mEMbFttZIBZ13EJPvQ==" }, - "System.Security.Cryptography.Xml": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "5e5bI28T0x73AwTsbuFP4qSRzthmU2C0Gqgg3AZ3KTxmSyA+Uhk31puA3srdaeWaacVnHhLdJywCzqOiEpbO/w==", - "dependencies": { - "System.Security.AccessControl": "6.0.0", - "System.Security.Cryptography.Pkcs": "6.0.1" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" - }, - "System.Text.Json": { - "type": "Transitive", - "resolved": "9.0.0", - "contentHash": "js7+qAu/9mQvnhA4EfGMZNEzXtJCDxgkgj8ohuxq/Qxv+R56G+ljefhiJHOxTNiw54q8vmABCWUwkMulNdlZ4A==" - }, "cringebootstrap.abstractions": { "type": "Project" }, @@ -370,6 +444,7 @@ "type": "Project", "dependencies": { "ImGui.NET.DirectX": "[1.91.0.1, )", + "JsonSchema.Net.Generation": "[5.0.2, )", "Lib.Harmony.Thin": "[2.3.4-torch, )", "NLog": "[5.4.0, )", "NuGet": "[1.0.0, )", @@ -418,12 +493,7 @@ "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" - } + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" }, "Steamworks.NET": { "type": "Transitive", @@ -434,24 +504,6 @@ "type": "Transitive", "resolved": "9.0.4", "contentHash": "getRQEXD8idlpb1KW56XuxImMy0FKp2WJPDf3Qr0kI/QKxxJSftqfDFVo0DZ3HCJRLU73qHSruv5q2l5O47jQQ==" - }, - "System.Security.AccessControl": { - "type": "Transitive", - "resolved": "6.0.0", - "contentHash": "AUADIc0LIEQe7MzC+I0cl0rAT8RrTAKFHl53yHjEUzNVIaUlhFY11vc2ebiVJzVBuOzun6F7FBA+8KAbGTTedQ==" - }, - "System.Security.Cryptography.Pkcs": { - "type": "Transitive", - "resolved": "6.0.1", - "contentHash": "ynmbW2GjIGg9K1wXmVIRs4IlyDolf0JXNpzFQ8JCVgwM+myUC2JeUggl2PwQig2PNVMegKmN1aAx7WPQ8tI3vA==", - "dependencies": { - "System.Formats.Asn1": "6.0.0" - } - }, - "System.Security.Principal.Windows": { - "type": "Transitive", - "resolved": "5.0.0", - "contentHash": "t0MGLukB5WAVU9bO3MGzvlGnyJPgUlcwerXn1kzBRjwLKixT96XV0Uza41W49gVd8zEMFu9vQEFlv0IOrytICA==" } } } diff --git a/CringePlugins/Config/ConfigHandler.cs b/CringePlugins/Config/ConfigHandler.cs new file mode 100644 index 0000000..81eac04 --- /dev/null +++ b/CringePlugins/Config/ConfigHandler.cs @@ -0,0 +1,151 @@ +using System.Text.Json; +using System.Text.Json.Nodes; +using CringePlugins.Config.Spec; +using Json.Schema; +using Json.Schema.Generation; +using NLog; +using NuGet; + +namespace CringePlugins.Config; + +public sealed class ConfigHandler +{ + private static readonly Logger Log = LogManager.GetCurrentClassLogger(); + + private readonly DirectoryInfo _configDirectory; + private readonly JsonSerializerOptions _serializerOptions = new(NuGetClient.SerializerOptions) + { + WriteIndented = true, + AllowTrailingCommas = true, + ReadCommentHandling = JsonCommentHandling.Skip + }; + + private readonly EvaluationOptions _evaluationOptions = new() + { + OutputFormat = OutputFormat.List, + RequireFormatValidation = true + }; + + public event EventHandler? ConfigReloaded; + + internal ConfigHandler(DirectoryInfo configDirectory) + { + _configDirectory = configDirectory; + } + + public ConfigReference RegisterConfig(string name, T? defaultInstance = null) where T : class + { + var spec = IConfigurationSpecProvider.FromType(typeof(T)); + + var path = Path.Join(_configDirectory.FullName, $"{name}.json"); + var backupPath = path + $".bak.{DateTimeOffset.Now.ToUnixTimeSeconds()}"; + + JsonNode? jsonNode = null; + if (File.Exists(path)) + { + using var stream = File.OpenRead(path); + try + { + jsonNode = JsonNode.Parse(stream, new JsonNodeOptions { PropertyNameCaseInsensitive = true }, + new JsonDocumentOptions { CommentHandling = JsonCommentHandling.Skip, AllowTrailingCommas = true }); + } + catch (JsonException e) + { + Log.Warn(e, "Failed to load config {Name}", name); + } + } + + var reference = new ConfigReference(name, this); + if (jsonNode == null || (spec != null && !TryValidate(name, spec, jsonNode))) + { + if (File.Exists(path)) + File.Move(path, backupPath); + defaultInstance ??= Activator.CreateInstance(); + RegisterChange(name, defaultInstance); + return reference; + } + + var instance = jsonNode.Deserialize(_serializerOptions)!; + ConfigReloaded?.Invoke(this, new ConfigValue(name, instance)); + + return reference; + } + + internal void RegisterChange(string name, T newValue) + { + var spec = IConfigurationSpecProvider.FromType(typeof(T)); + + var jsonNode = JsonSerializer.SerializeToNode(newValue, _serializerOptions)!; + + if (spec != null && !TryValidate(name, spec, jsonNode)) + throw new JsonException($"Supplied config value for {name} is invalid"); + + var path = Path.Join(_configDirectory.FullName, $"{name}.json"); + + using var stream = File.Create(path); + using var writer = new Utf8JsonWriter(stream, new() + { + Indented = true + }); + jsonNode.WriteTo(writer, _serializerOptions); + + ConfigReloaded?.Invoke(this, new ConfigValue(name, newValue)); + } + + private bool TryValidate(string name, JsonSchema schema, JsonNode jsonNode) + { + var results = schema.Evaluate(jsonNode, _evaluationOptions); + + if (results.IsValid) + return true; + + Log.Error("Config {Name} is invalid:", name); + foreach (var detail in results.Details) + { + Log.Error("Property {PropertyPath} is invalid:", detail.EvaluationPath); + foreach (var error in detail.Errors?.Values ?? []) + { + Log.Error("\t- {Error}", error); + } + } + + return false; + } + + public abstract record ConfigValue(string Name); + public sealed record ConfigValue(string Name, T Value) : ConfigValue(Name); +} + +public sealed class ConfigReference : IDisposable +{ + private readonly string _name; + private readonly ConfigHandler _instance; + private T? _value; + + public T Value + { + get => _value ?? throw new InvalidOperationException("Config has not been loaded yet"); + set => _instance.RegisterChange(_name, value); + } + + internal ConfigReference(string name, ConfigHandler instance) + { + _name = name; + _instance = instance; + instance.ConfigReloaded += InstanceOnConfigReloaded; + } + + private void InstanceOnConfigReloaded(object? sender, ConfigHandler.ConfigValue e) + { + if (e.Name != _name) return; + if (e is ConfigHandler.ConfigValue configValue) + _value = configValue.Value; + } + + public void Dispose() + { + _instance.ConfigReloaded -= InstanceOnConfigReloaded; + } + + public static implicit operator T(ConfigReference reference) => reference.Value; +} \ No newline at end of file diff --git a/CringePlugins/Config/Spec/IConfigurationSpecProvider.cs b/CringePlugins/Config/Spec/IConfigurationSpecProvider.cs new file mode 100644 index 0000000..67a54d8 --- /dev/null +++ b/CringePlugins/Config/Spec/IConfigurationSpecProvider.cs @@ -0,0 +1,21 @@ +using System.Reflection; +using Json.Schema; +using Json.Schema.Generation; + +namespace CringePlugins.Config.Spec; + +public interface IConfigurationSpecProvider +{ + static abstract JsonSchema Spec { get; } + + static JsonSchema? FromType(Type type) + { + if (type.IsAssignableTo(typeof(IConfigurationSpecProvider))) + { + return (JsonSchema)type.GetProperty(nameof(Spec), BindingFlags.Static | BindingFlags.Public | BindingFlags.DeclaredOnly)! + .GetValue(null)!; + } + + return null; + } +} \ No newline at end of file diff --git a/CringePlugins/CringePlugins.csproj b/CringePlugins/CringePlugins.csproj index 8034bdf..bd3c025 100644 --- a/CringePlugins/CringePlugins.csproj +++ b/CringePlugins/CringePlugins.csproj @@ -8,6 +8,7 @@ true true true + preview @@ -23,6 +24,7 @@ + diff --git a/CringePlugins/Loader/PluginsLifetime.cs b/CringePlugins/Loader/PluginsLifetime.cs index 9a932d4..d32f46c 100644 --- a/CringePlugins/Loader/PluginsLifetime.cs +++ b/CringePlugins/Loader/PluginsLifetime.cs @@ -13,10 +13,11 @@ using NuGet.Frameworks; using NuGet.Models; using NuGet.Versioning; using SharedCringe.Loader; +using VRage.FileSystem; namespace CringePlugins.Loader; -public class PluginsLifetime(string gameFolder) : ILoadingStage +public class PluginsLifetime(ConfigHandler configHandler, HttpClient client) : ILoadingStage { public static ImmutableArray Contexts { get; private set; } = []; @@ -28,53 +29,43 @@ public class PluginsLifetime(string gameFolder) : ILoadingStage // TODO move this as api for other plugins private readonly DirectoryInfo _dir = Directory.CreateDirectory(Path.Join(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "CringeLauncher")); private readonly NuGetRuntimeFramework _runtimeFramework = new(NuGetFramework.ParseFolder("net9.0-windows10.0.19041.0"), RuntimeInformation.RuntimeIdentifier); + + private ConfigReference? _configReference; public async ValueTask Load(ISplashProgress progress) { progress.DefineStepsCount(6); - + progress.Report("Discovering local plugins"); - + DiscoverLocalPlugins(_dir.CreateSubdirectory("plugins")); - + progress.Report("Loading config"); - PackagesConfig? packagesConfig = null; + _configReference = configHandler.RegisterConfig("packages", PackagesConfig.Default); + var packagesConfig = _configReference.Value; - var configDir = _dir.CreateSubdirectory("config"); - var configPath = Path.Join(configDir.FullName, "packages.json"); - if (File.Exists(configPath)) - await using (var stream = File.OpenRead(configPath)) - packagesConfig = await JsonSerializer.DeserializeAsync(stream, NuGetClient.SerializerOptions)!; - - if (packagesConfig == null) - { - packagesConfig = PackagesConfig.Default; - await using var stream = File.Create(configPath); - await JsonSerializer.SerializeAsync(stream, packagesConfig, NuGetClient.SerializerOptions); - } - progress.Report("Resolving packages"); - var sourceMapping = new PackageSourceMapping(packagesConfig.Sources); + var sourceMapping = new PackageSourceMapping(packagesConfig.Sources, client); // TODO take into account the target framework runtime identifier var resolver = new PackageResolver(_runtimeFramework.Framework, packagesConfig.Packages, sourceMapping); var packages = await resolver.ResolveAsync(); - + progress.Report("Downloading packages"); var builtInPackages = await BuiltInPackages.GetPackagesAsync(_runtimeFramework); var cachedPackages = await resolver.DownloadPackagesAsync(_dir.CreateSubdirectory("cache"), packages, builtInPackages.Keys.ToHashSet(), progress); - + progress.Report("Loading plugins"); //we can move this, but it should be before plugin init RenderHandler.Current.RegisterComponent(new NotificationsComponent()); await LoadPlugins(cachedPackages, sourceMapping, packagesConfig, builtInPackages); - - RenderHandler.Current.RegisterComponent(new PluginListComponent(packagesConfig, sourceMapping, configPath, gameFolder, _plugins)); + + RenderHandler.Current.RegisterComponent(new PluginListComponent(_configReference, sourceMapping, MyFileSystem.ExePath, _plugins)); } public void RegisterLifetime() diff --git a/CringePlugins/Services/GameServicesExtension.cs b/CringePlugins/Services/GameServicesExtension.cs new file mode 100644 index 0000000..47dcae0 --- /dev/null +++ b/CringePlugins/Services/GameServicesExtension.cs @@ -0,0 +1,13 @@ +using Sandbox; + +namespace CringePlugins.Services; + +public static class GameServicesExtension +{ + internal static IServiceProvider GameServices { get; set; } = null!; + + extension(MySandboxGame) + { + public static IServiceProvider Services => GameServices; + } +} \ No newline at end of file diff --git a/CringePlugins/Ui/PluginListComponent.cs b/CringePlugins/Ui/PluginListComponent.cs index afa5763..d36dd64 100644 --- a/CringePlugins/Ui/PluginListComponent.cs +++ b/CringePlugins/Ui/PluginListComponent.cs @@ -32,25 +32,23 @@ internal class PluginListComponent : IRenderComponent private bool _changed; private bool _open = true; - private PackagesConfig _packagesConfig; + private readonly ConfigReference _packagesConfig; private readonly PackageSourceMapping _sourceMapping; private readonly JsonSerializerOptions _serializerOptions = new(JsonSerializerDefaults.Web); private ImmutableHashSet? _selectedSources; - private readonly string _configPath; private readonly string _gameFolder; private ImmutableArray _plugins; private (SearchResultEntry entry, NuGetClient client)? _selected; private (PackageSource source, int index)? _selectedSource; - public PluginListComponent(PackagesConfig packagesConfig, PackageSourceMapping sourceMapping, string configPath, string gameFolder, + public PluginListComponent(ConfigReference packagesConfig, PackageSourceMapping sourceMapping, string gameFolder, ImmutableArray plugins) { _packagesConfig = packagesConfig; _sourceMapping = sourceMapping; - _configPath = configPath; _gameFolder = gameFolder; _plugins = plugins; - _packages = packagesConfig.Packages.ToImmutableDictionary(b => b.Id, b => b.Range, + _packages = packagesConfig.Value.Packages.ToImmutableDictionary(b => b.Id, b => b.Range, StringComparer.OrdinalIgnoreCase); MyScreenManager.ScreenAdded += ScreenChanged; @@ -153,9 +151,9 @@ internal class PluginListComponent : IRenderComponent TableSetupColumn("Url", ImGuiTableColumnFlags.None, .8f); TableHeadersRow(); - for (var index = 0; index < _packagesConfig.Sources.Length; index++) + for (var index = 0; index < _packagesConfig.Value.Sources.Length; index++) { - var source = _packagesConfig.Sources[index]; + var source = _packagesConfig.Value.Sources[index]; TableNextRow(); TableNextColumn(); @@ -211,15 +209,15 @@ internal class PluginListComponent : IRenderComponent if (Button("Save")) { - var array = _packagesConfig.Sources.RemoveAt(index).Insert(index, selectedSource); + var array = _packagesConfig.Value.Sources.RemoveAt(index).Insert(index, selectedSource); - _packagesConfig = _packagesConfig with + _packagesConfig.Value = _packagesConfig.Value with { Sources = array }; _selectedSource = null; - + Save(); } @@ -227,15 +225,15 @@ internal class PluginListComponent : IRenderComponent if (Button("Delete")) { - var array = _packagesConfig.Sources.RemoveAt(index); + var array = _packagesConfig.Value.Sources.RemoveAt(index); - _packagesConfig = _packagesConfig with + _packagesConfig.Value = _packagesConfig.Value with { Sources = array }; _selectedSource = null; - + Save(); } } @@ -246,10 +244,10 @@ internal class PluginListComponent : IRenderComponent if (Button("Add New")) { var source = new PackageSource("source name", "", "https://url.to/index.json"); - - var array = _packagesConfig.Sources.Add(source); - _packagesConfig = _packagesConfig with + var array = _packagesConfig.Value.Sources.Add(source); + + _packagesConfig.Value = _packagesConfig.Value with { Sources = array }; @@ -274,11 +272,11 @@ internal class PluginListComponent : IRenderComponent if (configSerializer.Deserialize(fs) is PluginLoaderConfig oldConfig) { - _packagesConfig = oldConfig.MigratePlugins(_packagesConfig); + _packagesConfig.Value = oldConfig.MigratePlugins(_packagesConfig); Save(false); - _packages = _packagesConfig.Packages.ToImmutableDictionary(b => b.Id, b => b.Range, StringComparer.OrdinalIgnoreCase); + _packages = _packagesConfig.Value.Packages.ToImmutableDictionary(b => b.Id, b => b.Range, StringComparer.OrdinalIgnoreCase); } } @@ -346,15 +344,15 @@ internal class PluginListComponent : IRenderComponent _selectedSources.Count > 2 ? $"{_selectedSources.First().Name} +{_selectedSources.Count - 1}" : string.Join(",", _selectedSources.Select(b => b.Name)), ImGuiComboFlags.WidthFitPreview)) { - foreach (var source in _packagesConfig.Sources) + foreach (var source in _packagesConfig.Value.Sources) { var selected = _selectedSources?.Contains(source) ?? true; if (Selectable(source.Name, ref selected)) { _selectedSources = selected - ? (_selectedSources?.Count ?? 0) + 1 == _packagesConfig.Sources.Length ? null : _selectedSources?.Add(source) - : (_selectedSources ?? _packagesConfig.Sources.ToImmutableHashSet()).Remove(source); - + ? (_selectedSources?.Count ?? 0) + 1 == _packagesConfig.Value.Sources.Length ? null : _selectedSources?.Add(source) + : (_selectedSources ?? _packagesConfig.Value.Sources.ToImmutableHashSet()).Remove(source); + _searchTask = RefreshAsync(); return; } @@ -488,7 +486,7 @@ internal class PluginListComponent : IRenderComponent Text("Pulled from"); SameLine(); var url = _selected.Value.client.ToString(); - TextLinkOpenURL(_packagesConfig.Sources.FirstOrDefault(b => b.Url == url)?.Name ?? url, url); + TextLinkOpenURL(_packagesConfig.Value.Sources.FirstOrDefault(b => b.Url == url)?.Name ?? url, url); if (selected.Authors is not null) { @@ -563,14 +561,12 @@ internal class PluginListComponent : IRenderComponent private void Save(bool keepPackages = true) { - _changed = true; - - using var stream = File.Create(_configPath); - - JsonSerializer.Serialize(stream, keepPackages ? _packagesConfig with + _packagesConfig.Value = keepPackages ? _packagesConfig.Value with { - Packages = [.._packages.Select(b => new PackageReference(b.Key, b.Value))] - } : _packagesConfig, NuGetClient.SerializerOptions); + Packages = [.. _packages.Select(b => new PackageReference(b.Key, b.Value))] + } : _packagesConfig; + + _changed = true; } private static unsafe int ComparePlugins(PluginInstance x, PluginInstance y, ImGuiTableSortSpecsPtr specs) diff --git a/CringePlugins/packages.lock.json b/CringePlugins/packages.lock.json index bc8f15f..4be9367 100644 --- a/CringePlugins/packages.lock.json +++ b/CringePlugins/packages.lock.json @@ -21,11 +21,16 @@ "type": "Direct", "requested": "[1.91.0.1, )", "resolved": "1.91.0.1", - "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==", + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" + }, + "JsonSchema.Net.Generation": { + "type": "Direct", + "requested": "[5.0.2, )", + "resolved": "5.0.2", + "contentHash": "+khIPgLqOyFOWjgHSzXMjJijwbQb85/cFRf4NwTaV6QBoGM9IT8LeLCnmwazruwKsx16HB1UFX3mslUujfjVpg==", "dependencies": { - "System.Buffers": "4.5.1", - "System.Numerics.Vectors": "4.5.0", - "System.Runtime.CompilerServices.Unsafe": "6.0.0" + "Humanizer.Core": "2.14.1", + "JsonSchema.Net": "7.3.4" } }, "Krafs.Publicizer": { @@ -40,8 +45,7 @@ "resolved": "2.3.4-torch", "contentHash": "UnLUnLLiXfHZdKa1zhi6w8cl8tJTrpVixLtvjFEVtlDA6Rkf06OcZ2gSidcbcgKjTcR+fk5Qsdos3mU5oohzfg==", "dependencies": { - "MonoMod.Core": "1.2.2", - "System.Text.Json": "9.0.0" + "MonoMod.Core": "1.2.2" } }, "NLog": { @@ -53,8 +57,8 @@ "SpaceEngineersDedicated.ReferenceAssemblies": { "type": "Direct", "requested": "[1.*, )", - "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" @@ -66,6 +70,33 @@ "resolved": "20.1.0", "contentHash": "+GntwnyJ5tCNvUIaQxv2+ehDvZJzGUqlSB5xRBk1hTj1qqBJ6s4vK/OfGD/jae7aTmXiGSm8wpJORosNtQevJQ==" }, + "Humanizer.Core": { + "type": "Transitive", + "resolved": "2.14.1", + "contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw==" + }, + "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" + } + }, "Microsoft.Bcl.AsyncInterfaces": { "type": "Transitive", "resolved": "6.0.0", @@ -81,9 +112,7 @@ "resolved": "4.11.0", "contentHash": "djf8ujmqYImFgB04UGtcsEhHrzVqzHowS+EEl/Yunc5LdrYrZhGBWUTXoCF0NzYXJxtfuD+UVQarWpvrNc94Qg==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "3.3.4", - "System.Collections.Immutable": "8.0.0", - "System.Reflection.Metadata": "8.0.0" + "Microsoft.CodeAnalysis.Analyzers": "3.3.4" } }, "Mono.Cecil": { @@ -145,16 +174,6 @@ "resolved": "4.2.0-keen-cringe", "contentHash": "LaJN3h1Gi1FWVdef2I5WtOH9gwzKCBniH0CragarbkN2QheYY6Lqm+91PcOfp1w/4wdVb+k8Kjv3sO393Tphtw==" }, - "System.Buffers": { - "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "Rw7ijyl1qqRS0YQD/WycNst8hUUMgrMH4FCn1nNm27M4VxchZ1js3fVjQaANHO5f3sN4isvP4a+Met9Y4YomAg==" - }, - "System.Collections.Immutable": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "AurL6Y5BA1WotzlEvVaIDpqzpIPvYnnldxru8oXJU2yFxFUy3+pNXjXd1ymO+RA0rq0+590Q8gaz2l3Sr7fmqg==" - }, "System.Linq.Async": { "type": "Transitive", "resolved": "6.0.1", @@ -163,29 +182,6 @@ "Microsoft.Bcl.AsyncInterfaces": "6.0.0" } }, - "System.Numerics.Vectors": { - "type": "Transitive", - "resolved": "4.5.0", - "contentHash": "QQTlPTl06J/iiDbJCiepZ4H//BVraReU4O4EoRw1U02H5TLUIT7xn3GnDp9AXPSlJUDyFs4uWjWafNX6WrAojQ==" - }, - "System.Reflection.Metadata": { - "type": "Transitive", - "resolved": "8.0.0", - "contentHash": "ptvgrFh7PvWI8bcVqG5rsA/weWM09EnthFHR5SCnS6IN+P4mj6rE1lBDC4U8HL9/57htKAqy4KQ3bBj84cfYyQ==", - "dependencies": { - "System.Collections.Immutable": "8.0.0" - } - }, - "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==" - }, "cringebootstrap.abstractions": { "type": "Project" }, @@ -211,12 +207,7 @@ "type": "Direct", "requested": "[1.91.0.1, )", "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" - } + "contentHash": "PpW1gQ9g97h6Hm/h/tkSBOmsBYgGwN8wKNmlJomcQFD/zRY1HPkJZz18XRSfRLHPmH2eeh4hhhZv1KHug7dF9g==" }, "Steamworks.NET": { "type": "Direct", diff --git a/NuGet/NuGetClient.cs b/NuGet/NuGetClient.cs index f21a4e1..16ea945 100644 --- a/NuGet/NuGetClient.cs +++ b/NuGet/NuGetClient.cs @@ -97,43 +97,20 @@ public class NuGetClient return _client.GetFromJsonAsync(builder.Uri, SerializerOptions)!; } - public static async Task CreateFromIndexUrlAsync(string indexUrl) + public static async Task CreateFromIndexUrlAsync(string indexUrl, HttpClient client) { - var client = new HttpClient(new HttpClientHandler - { - AutomaticDecompression = DecompressionMethods.All, - }); + var index = await client.GetFromJsonAsync(indexUrl, SerializerOptions); - NuGetClient? ngClient = null; + var (packageBaseAddress, _, _) = index!.Resources.First(b => b.Type.Id == "PackageBaseAddress"); + var (registration, _, _) = index.Resources.First(b => b.Type.Id == "RegistrationsBaseUrl"); + var (search, _, _) = index.Resources.First(b => b.Type.Id == "SearchQueryService"); - const int MaxRetries = 10; + if (!packageBaseAddress.EndsWith('/')) + packageBaseAddress += '/'; + if (!registration.EndsWith('/')) + registration += '/'; - for (var i = 0; i < MaxRetries; i++) - { - try - { - var index = await client.GetFromJsonAsync(indexUrl, SerializerOptions); - - var (packageBaseAddress, _, _) = index!.Resources.First(b => b.Type.Id == "PackageBaseAddress"); - var (registration, _, _) = index.Resources.First(b => b.Type.Id == "RegistrationsBaseUrl"); - var (search, _, _) = index.Resources.First(b => b.Type.Id == "SearchQueryService"); - - if (!packageBaseAddress.EndsWith('/')) - packageBaseAddress += '/'; - if (!registration.EndsWith('/')) - registration += '/'; - - ngClient = new NuGetClient(new Uri(indexUrl), client, new Uri(packageBaseAddress), new Uri(registration), new Uri(search)); - - break; - } - catch (HttpRequestException ex) - { - Console.WriteLine(ex.Message); - } - } - - return ngClient; + return new NuGetClient(new Uri(indexUrl), client, new Uri(packageBaseAddress), new Uri(registration), new Uri(search)); } public override string ToString() => _index.ToString(); diff --git a/NuGet/PackageSourceMapping.cs b/NuGet/PackageSourceMapping.cs index 51a6d66..38939ac 100644 --- a/NuGet/PackageSourceMapping.cs +++ b/NuGet/PackageSourceMapping.cs @@ -5,12 +5,12 @@ using System.Text.RegularExpressions; namespace NuGet; -public class PackageSourceMapping(ImmutableArray sources) +public class PackageSourceMapping(ImmutableArray sources, HttpClient client) { private readonly ImmutableArray<(string pattern, Task client)> _clients = [ ..sources.Select(b => (b.Pattern, - NuGetClient.CreateFromIndexUrlAsync(b.Url))) + NuGetClient.CreateFromIndexUrlAsync(b.Url, client))) ]; public Task GetClientAsync(string packageId) => 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