- add: DotNet runtime download
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using Nebula.Launcher.Models;
|
using Nebula.Launcher.Models;
|
||||||
using Nebula.Launcher.ViewModels.Pages;
|
using Nebula.Launcher.ViewModels.Pages;
|
||||||
using Nebula.Shared.Services;
|
using Nebula.Shared.Services;
|
||||||
@@ -32,4 +33,6 @@ public static class LauncherConVar
|
|||||||
public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", "en-US");
|
public static readonly ConVar<string> CurrentLang = ConVarBuilder.Build<string>("launcher.language", "en-US");
|
||||||
public static readonly ConVar<string> ILSpyUrl = ConVarBuilder.Build<string>("decompiler.url",
|
public static readonly ConVar<string> ILSpyUrl = ConVarBuilder.Build<string>("decompiler.url",
|
||||||
"https://github.com/icsharpcode/ILSpy/releases/download/v9.0/ILSpy_binaries_9.0.0.7889-x64.zip");
|
"https://github.com/icsharpcode/ILSpy/releases/download/v9.0/ILSpy_binaries_9.0.0.7889-x64.zip");
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,11 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase, IContentHol
|
|||||||
|
|
||||||
public void OnBackEnter()
|
public void OnBackEnter()
|
||||||
{
|
{
|
||||||
|
if (CurrentEntry.Parent is null)
|
||||||
|
{
|
||||||
|
SetHubRoot();
|
||||||
|
return;
|
||||||
|
}
|
||||||
CurrentEntry.Parent?.GoCurrent();
|
CurrentEntry.Parent?.GoCurrent();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,6 +121,8 @@ public sealed partial class ContentBrowserViewModel : ViewModelBase, IContentHol
|
|||||||
|
|
||||||
public void SetHubRoot()
|
public void SetHubRoot()
|
||||||
{
|
{
|
||||||
|
ServerText = string.Empty;
|
||||||
|
SearchText = string.Empty;
|
||||||
var root = ViewHelperService.GetViewModel<ServerListContentEntry>();
|
var root = ViewHelperService.GetViewModel<ServerListContentEntry>();
|
||||||
root.InitHubList(this);
|
root.InitHubList(this);
|
||||||
CurrentEntry = root;
|
CurrentEntry = root;
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public partial class ServerEntryModelView : ViewModelBase, IFilterConsumer
|
|||||||
[GenerateProperty] private RestService RestService { get; } = default!;
|
[GenerateProperty] private RestService RestService { get; } = default!;
|
||||||
[GenerateProperty] private MainViewModel MainViewModel { get; } = default!;
|
[GenerateProperty] private MainViewModel MainViewModel { get; } = default!;
|
||||||
[GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; } = default!;
|
[GenerateProperty] private FavoriteServerListProvider FavoriteServerListProvider { get; } = default!;
|
||||||
|
[GenerateProperty] private DotnetResolverService DotnetResolverService { get; } = default!;
|
||||||
|
|
||||||
public ServerStatus Status { get; private set; } =
|
public ServerStatus Status { get; private set; } =
|
||||||
new(
|
new(
|
||||||
@@ -210,10 +211,10 @@ public partial class ServerEntryModelView : ViewModelBase, IFilterConsumer
|
|||||||
await RunnerService.PrepareRun(buildInfo, loadingContext, CancellationService.Token);
|
await RunnerService.PrepareRun(buildInfo, loadingContext, CancellationService.Token);
|
||||||
|
|
||||||
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
var path = Path.GetDirectoryName(Assembly.GetEntryAssembly()?.Location);
|
||||||
|
|
||||||
Process = Process.Start(new ProcessStartInfo
|
Process = Process.Start(new ProcessStartInfo
|
||||||
{
|
{
|
||||||
FileName = "dotnet.exe",
|
FileName = await DotnetResolverService.EnsureDotnet(),
|
||||||
Arguments = Path.Join(path, "Nebula.Runner.dll"),
|
Arguments = Path.Join(path, "Nebula.Runner.dll"),
|
||||||
Environment =
|
Environment =
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,4 +28,11 @@ public static class CurrentConVar
|
|||||||
ConVarBuilder.Build<Dictionary<string, EngineVersionInfo>>("engine.manifest.backup");
|
ConVarBuilder.Build<Dictionary<string, EngineVersionInfo>>("engine.manifest.backup");
|
||||||
public static readonly ConVar<ModulesInfo> ModuleManifestBackup =
|
public static readonly ConVar<ModulesInfo> ModuleManifestBackup =
|
||||||
ConVarBuilder.Build<ModulesInfo>("module.manifest.backup");
|
ConVarBuilder.Build<ModulesInfo>("module.manifest.backup");
|
||||||
|
|
||||||
|
public static readonly ConVar<Dictionary<string,string>> DotnetUrl = ConVarBuilder.Build<Dictionary<string,string>>("dotnet.url",
|
||||||
|
new(){
|
||||||
|
{"win-x64", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-win-x64.zip"},
|
||||||
|
{"win-x86", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-win-x86.zip"},
|
||||||
|
{"linux-x64", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-linux-x64.tar.gz"}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
70
Nebula.Shared/Services/DotnetResolverService.cs
Normal file
70
Nebula.Shared/Services/DotnetResolverService.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Nebula.Shared.Services;
|
||||||
|
|
||||||
|
[ServiceRegister]
|
||||||
|
public class DotnetResolverService(DebugService debugService, ConfigurationService configurationService)
|
||||||
|
{
|
||||||
|
private HttpClient _httpClient = new HttpClient();
|
||||||
|
|
||||||
|
private static readonly string FullPath = Path.Join(FileService.RootPath, "dotnet", DotnetUrlHelper.GetRuntimeIdentifier());
|
||||||
|
private static readonly string ExecutePath = Path.Join(FullPath, "dotnet" + DotnetUrlHelper.GetExtension());
|
||||||
|
|
||||||
|
public async Task<string> EnsureDotnet(){
|
||||||
|
if(!Directory.Exists(FullPath))
|
||||||
|
await Download();
|
||||||
|
|
||||||
|
return ExecutePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task Download(){
|
||||||
|
|
||||||
|
debugService.GetLogger("DotnetResolver").Log($"Downloading dotnet {DotnetUrlHelper.GetRuntimeIdentifier()}...");
|
||||||
|
var ridExt =
|
||||||
|
DotnetUrlHelper.GetCurrentPlatformDotnetUrl(configurationService.GetConfigValue(CurrentConVar.DotnetUrl)!);
|
||||||
|
using var response = await _httpClient.GetAsync(ridExt);
|
||||||
|
using var zipArchive = new ZipArchive(await response.Content.ReadAsStreamAsync());
|
||||||
|
Directory.CreateDirectory(FullPath);
|
||||||
|
zipArchive.ExtractToDirectory(FullPath);
|
||||||
|
debugService.GetLogger("DotnetResolver").Log($"Downloading dotnet complete.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DotnetUrlHelper
|
||||||
|
{
|
||||||
|
public static string GetExtension()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows()) return ".exe";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCurrentPlatformDotnetUrl(Dictionary<string, string> dotnetUrl)
|
||||||
|
{
|
||||||
|
string? rid = GetRuntimeIdentifier();
|
||||||
|
|
||||||
|
if (dotnetUrl.TryGetValue(rid, out var url))
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PlatformNotSupportedException($"No download URL available for the current platform: {rid}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetRuntimeIdentifier()
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return Environment.Is64BitProcess ? "win-x64" : "win-x86";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
return "linux-x64";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PlatformNotSupportedException("Unsupported operating system");
|
||||||
|
}
|
||||||
|
}
|
||||||
89
Nebula.UpdateResolver/DotnetStandalone.cs
Normal file
89
Nebula.UpdateResolver/DotnetStandalone.cs
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.IO;
|
||||||
|
using System.IO.Compression;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Nebula.UpdateResolver.Configuration;
|
||||||
|
|
||||||
|
namespace Nebula.UpdateResolver;
|
||||||
|
|
||||||
|
public static class DotnetStandalone
|
||||||
|
{
|
||||||
|
private static readonly HttpClient HttpClient = new HttpClient();
|
||||||
|
|
||||||
|
private static readonly string FullPath = Path.Join(MainWindow.RootPath, "dotnet", DotnetUrlHelper.GetRuntimeIdentifier());
|
||||||
|
private static readonly string ExecutePath = Path.Join(FullPath, "dotnet" + DotnetUrlHelper.GetExtension());
|
||||||
|
|
||||||
|
public static async Task<Process?> Run(string dllPath)
|
||||||
|
{
|
||||||
|
await EnsureDotnet();
|
||||||
|
|
||||||
|
return Process.Start(new ProcessStartInfo
|
||||||
|
{
|
||||||
|
FileName = ExecutePath,
|
||||||
|
Arguments = dllPath,
|
||||||
|
CreateNoWindow = true,
|
||||||
|
UseShellExecute = false,
|
||||||
|
RedirectStandardOutput = true,
|
||||||
|
RedirectStandardError = true,
|
||||||
|
StandardOutputEncoding = Encoding.UTF8
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task EnsureDotnet(){
|
||||||
|
if(!Directory.Exists(FullPath))
|
||||||
|
await Download();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task Download(){
|
||||||
|
|
||||||
|
LogStandalone.Log($"Downloading dotnet {DotnetUrlHelper.GetRuntimeIdentifier()}...");
|
||||||
|
var ridExt =
|
||||||
|
DotnetUrlHelper.GetCurrentPlatformDotnetUrl(ConfigurationStandalone.GetConfigValue(UpdateConVars.DotnetUrl)!);
|
||||||
|
using var response = await HttpClient.GetAsync(ridExt);
|
||||||
|
using var zipArchive = new ZipArchive(await response.Content.ReadAsStreamAsync());
|
||||||
|
Directory.CreateDirectory(FullPath);
|
||||||
|
zipArchive.ExtractToDirectory(FullPath);
|
||||||
|
LogStandalone.Log($"Downloading dotnet complete.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class DotnetUrlHelper
|
||||||
|
{
|
||||||
|
public static string GetExtension()
|
||||||
|
{
|
||||||
|
if (OperatingSystem.IsWindows()) return ".exe";
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetCurrentPlatformDotnetUrl(Dictionary<string, string> dotnetUrl)
|
||||||
|
{
|
||||||
|
string? rid = GetRuntimeIdentifier();
|
||||||
|
|
||||||
|
if (dotnetUrl.TryGetValue(rid, out var url))
|
||||||
|
{
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PlatformNotSupportedException($"No download URL available for the current platform: {rid}");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string GetRuntimeIdentifier()
|
||||||
|
{
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||||
|
{
|
||||||
|
return Environment.Is64BitProcess ? "win-x64" : "win-x86";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||||
|
{
|
||||||
|
return "linux-x64";
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new PlatformNotSupportedException("Unsupported operating system");
|
||||||
|
}
|
||||||
|
}
|
||||||
21
Nebula.UpdateResolver/LogStandalone.cs
Normal file
21
Nebula.UpdateResolver/LogStandalone.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Nebula.UpdateResolver;
|
||||||
|
|
||||||
|
public static class LogStandalone
|
||||||
|
{
|
||||||
|
public static Action<string, int>? OnLog;
|
||||||
|
|
||||||
|
public static void LogError(Exception e){
|
||||||
|
Log($"{e.GetType().Name}: "+ e.Message);
|
||||||
|
Log(e.StackTrace);
|
||||||
|
if(e.InnerException != null)
|
||||||
|
LogError(e.InnerException);
|
||||||
|
}
|
||||||
|
public static void Log(string? message, int percentage = 0)
|
||||||
|
{
|
||||||
|
if(message is null) return;
|
||||||
|
|
||||||
|
OnLog?.Invoke(message, percentage);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,6 +23,19 @@ public partial class MainWindow : Window
|
|||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
LogStandalone.OnLog += (message, percentage) =>
|
||||||
|
{
|
||||||
|
ProgressLabel.Content = message;
|
||||||
|
if (percentage == 0)
|
||||||
|
PercentLabel.Content = "";
|
||||||
|
else
|
||||||
|
PercentLabel.Content = percentage + "%";
|
||||||
|
|
||||||
|
var messageOut =
|
||||||
|
$"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd HH:mm:ss}]: {message} {PercentLabel.Content}";
|
||||||
|
Console.WriteLine(messageOut);
|
||||||
|
LogStr += messageOut + "\n";
|
||||||
|
};
|
||||||
Start();
|
Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -31,11 +44,11 @@ public partial class MainWindow : Window
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var info = await EnsureFiles();
|
var info = await EnsureFiles();
|
||||||
Log("Downloading files...");
|
LogStandalone.Log("Downloading files...");
|
||||||
|
|
||||||
foreach (var file in info.ToDelete)
|
foreach (var file in info.ToDelete)
|
||||||
{
|
{
|
||||||
Log("Deleting " + file.Path);
|
LogStandalone.Log("Deleting " + file.Path);
|
||||||
FileApi.Remove(file.Path);
|
FileApi.Remove(file.Path);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,30 +68,21 @@ public partial class MainWindow : Window
|
|||||||
await using var stream = await response.Content.ReadAsStreamAsync();
|
await using var stream = await response.Content.ReadAsStreamAsync();
|
||||||
FileApi.Save(file.Path, stream);
|
FileApi.Save(file.Path, stream);
|
||||||
resolved++;
|
resolved++;
|
||||||
Log("Saving " + file.Path, (int)(resolved / (float)count * 100f));
|
LogStandalone.Log("Saving " + file.Path, (int)(resolved / (float)count * 100f));
|
||||||
|
|
||||||
loadedManifest.Add(file);
|
loadedManifest.Add(file);
|
||||||
Save(loadedManifest);
|
Save(loadedManifest);
|
||||||
}
|
}
|
||||||
|
|
||||||
Log("Download finished. Running launcher...");
|
LogStandalone.Log("Download finished. Running launcher...");
|
||||||
|
|
||||||
var process = Process.Start(new ProcessStartInfo
|
await DotnetStandalone.Run(Path.Join(FileApi.RootPath, "Nebula.Launcher.dll"));
|
||||||
{
|
|
||||||
FileName = "dotnet.exe",
|
|
||||||
Arguments = Path.Join(FileApi.RootPath, "Nebula.Launcher.dll"),
|
|
||||||
CreateNoWindow = true,
|
|
||||||
UseShellExecute = false,
|
|
||||||
RedirectStandardOutput = true,
|
|
||||||
RedirectStandardError = true,
|
|
||||||
StandardOutputEncoding = Encoding.UTF8
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
catch(HttpRequestException e){
|
catch(HttpRequestException e){
|
||||||
LogError(e);
|
LogStandalone.LogError(e);
|
||||||
Log("Проблемы с интернет-соединением...");
|
LogStandalone.Log("Network connection error...");
|
||||||
var logPath = Path.Join(RootPath,"updateResloverError.txt");
|
var logPath = Path.Join(RootPath,"updateResloverError.txt");
|
||||||
File.WriteAllText(logPath, LogStr);
|
await File.WriteAllTextAsync(logPath, LogStr);
|
||||||
Process.Start(new ProcessStartInfo(){
|
Process.Start(new ProcessStartInfo(){
|
||||||
FileName = "notepad",
|
FileName = "notepad",
|
||||||
Arguments = logPath
|
Arguments = logPath
|
||||||
@@ -86,9 +90,9 @@ public partial class MainWindow : Window
|
|||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
LogError(e);
|
LogStandalone.LogError(e);
|
||||||
var logPath = Path.Join(RootPath,"updateResloverError.txt");
|
var logPath = Path.Join(RootPath,"updateResloverError.txt");
|
||||||
File.WriteAllText(logPath, LogStr);
|
await File.WriteAllTextAsync(logPath, LogStr);
|
||||||
Process.Start(new ProcessStartInfo(){
|
Process.Start(new ProcessStartInfo(){
|
||||||
FileName = "notepad",
|
FileName = "notepad",
|
||||||
Arguments = logPath
|
Arguments = logPath
|
||||||
@@ -102,7 +106,7 @@ public partial class MainWindow : Window
|
|||||||
|
|
||||||
private async Task<ManifestEnsureInfo> EnsureFiles()
|
private async Task<ManifestEnsureInfo> EnsureFiles()
|
||||||
{
|
{
|
||||||
Log("Ensuring launcher manifest...");
|
LogStandalone.Log("Ensuring launcher manifest...");
|
||||||
var manifest = await RestStandalone.GetAsync<LauncherManifest>(
|
var manifest = await RestStandalone.GetAsync<LauncherManifest>(
|
||||||
new Uri(ConfigurationStandalone.GetConfigValue(UpdateConVars.UpdateCacheUrl)! + "/manifest.json"), CancellationToken.None);
|
new Uri(ConfigurationStandalone.GetConfigValue(UpdateConVars.UpdateCacheUrl)! + "/manifest.json"), CancellationToken.None);
|
||||||
|
|
||||||
@@ -110,10 +114,10 @@ public partial class MainWindow : Window
|
|||||||
var toDelete = new HashSet<LauncherManifestEntry>();
|
var toDelete = new HashSet<LauncherManifestEntry>();
|
||||||
var filesExist = new HashSet<LauncherManifestEntry>();
|
var filesExist = new HashSet<LauncherManifestEntry>();
|
||||||
|
|
||||||
Log("Manifest loaded!");
|
LogStandalone.Log("Manifest loaded!");
|
||||||
if (ConfigurationStandalone.TryGetConfigValue(UpdateConVars.CurrentLauncherManifest, out var currentManifest))
|
if (ConfigurationStandalone.TryGetConfigValue(UpdateConVars.CurrentLauncherManifest, out var currentManifest))
|
||||||
{
|
{
|
||||||
Log("Delta manifest loaded!");
|
LogStandalone.Log("Delta manifest loaded!");
|
||||||
foreach (var file in currentManifest.Entries)
|
foreach (var file in currentManifest.Entries)
|
||||||
{
|
{
|
||||||
if (!manifest.Entries.Contains(file))
|
if (!manifest.Entries.Contains(file))
|
||||||
@@ -133,31 +137,11 @@ public partial class MainWindow : Window
|
|||||||
toDownload = manifest.Entries;
|
toDownload = manifest.Entries;
|
||||||
}
|
}
|
||||||
|
|
||||||
Log("Saving launcher manifest...");
|
LogStandalone.Log("Saving launcher manifest...");
|
||||||
|
|
||||||
return new ManifestEnsureInfo(toDownload, toDelete, filesExist);
|
return new ManifestEnsureInfo(toDownload, toDelete, filesExist);
|
||||||
}
|
}
|
||||||
private void LogError(Exception e){
|
|
||||||
Log($"{e.GetType().Name}: "+ e.Message);
|
|
||||||
Log(e.StackTrace);
|
|
||||||
if(e.InnerException != null)
|
|
||||||
LogError(e.InnerException);
|
|
||||||
}
|
|
||||||
private void Log(string? message, int percentage = 0)
|
|
||||||
{
|
|
||||||
if(message is null) return;
|
|
||||||
|
|
||||||
ProgressLabel.Content = message;
|
|
||||||
if (percentage == 0)
|
|
||||||
PercentLabel.Content = "";
|
|
||||||
else
|
|
||||||
PercentLabel.Content = percentage + "%";
|
|
||||||
|
|
||||||
var messageOut = $"[{DateTime.Now.ToUniversalTime():yyyy-MM-dd HH:mm:ss}]: {message} {PercentLabel.Content}";
|
|
||||||
Console.WriteLine(messageOut);
|
|
||||||
LogStr += messageOut + "\n";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Save(HashSet<LauncherManifestEntry> entries)
|
private void Save(HashSet<LauncherManifestEntry> entries)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using Nebula.UpdateResolver.Configuration;
|
using Nebula.UpdateResolver.Configuration;
|
||||||
|
|
||||||
namespace Nebula.UpdateResolver;
|
namespace Nebula.UpdateResolver;
|
||||||
@@ -8,4 +9,11 @@ public static class UpdateConVars
|
|||||||
ConVarBuilder.Build<string>("update.url","https://durenko.tatar/nebula/manifest/");
|
ConVarBuilder.Build<string>("update.url","https://durenko.tatar/nebula/manifest/");
|
||||||
public static readonly ConVar<LauncherManifest> CurrentLauncherManifest =
|
public static readonly ConVar<LauncherManifest> CurrentLauncherManifest =
|
||||||
ConVarBuilder.Build<LauncherManifest>("update.manifest");
|
ConVarBuilder.Build<LauncherManifest>("update.manifest");
|
||||||
|
|
||||||
|
public static readonly ConVar<Dictionary<string,string>> DotnetUrl = ConVarBuilder.Build<Dictionary<string,string>>("dotnet.url",
|
||||||
|
new(){
|
||||||
|
{"win-x64", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-win-x64.zip"},
|
||||||
|
{"win-x86", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-win-x86.zip"},
|
||||||
|
{"linux-x64", "https://builds.dotnet.microsoft.com/dotnet/Runtime/9.0.6/dotnet-runtime-9.0.6-linux-x64.tar.gz"}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user