- tweak: fix resolving think
This commit is contained in:
@@ -4,6 +4,7 @@ using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Data.Core;
|
||||
using Avalonia.Data.Core.Plugins;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nebula.Launcher.ViewModels;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.2.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageReference Include="libsodium" Version="1.0.20" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -35,6 +36,13 @@
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="BuildCheck" AfterTargets="AfterBuild">
|
||||
<Copy SourceFiles="..\Nebula.Runner\bin\$(Configuration)\$(TargetFramework)\Nebula.Runner.dll" DestinationFolder="$(OutDir)"/>
|
||||
<Copy SourceFiles="..\Nebula.Runner\bin\$(Configuration)\$(TargetFramework)\Nebula.Runner.pdb" DestinationFolder="$(OutDir)"/>
|
||||
<Copy SourceFiles="..\Nebula.Runner\bin\$(Configuration)\$(TargetFramework)\Nebula.Runner.deps.json" DestinationFolder="$(OutDir)"/>
|
||||
<Copy SourceFiles="..\Nebula.Runner\bin\$(Configuration)\$(TargetFramework)\Nebula.Runner.runtimeconfig.json" DestinationFolder="$(OutDir)"/>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Nebula.Shared\Nebula.Shared.csproj" />
|
||||
|
||||
@@ -3,31 +3,106 @@ using System.Diagnostics;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using Nebula.Launcher.ViewHelper;
|
||||
using Nebula.Shared.Models;
|
||||
using Nebula.Shared.Services;
|
||||
|
||||
namespace Nebula.Launcher.ViewModels;
|
||||
|
||||
[ViewModelRegister(isSingleton:false)]
|
||||
public partial class ServerEntryModelView : ViewModelBase
|
||||
{
|
||||
private readonly AuthService _authService = default!;
|
||||
private readonly ContentService _contentService = default!;
|
||||
private readonly CancellationService _cancellationService = default!;
|
||||
private readonly DebugService _debugService = default!;
|
||||
private readonly RunnerService _runnerService;
|
||||
|
||||
[ObservableProperty] private bool _runVisible = true;
|
||||
|
||||
public ServerHubInfo ServerHubInfo { get; set; }
|
||||
public ServerHubInfo ServerHubInfo { get; set; } = default!;
|
||||
|
||||
public ServerEntryModelView() : base()
|
||||
{
|
||||
}
|
||||
|
||||
public ServerEntryModelView(IServiceProvider serviceProvider) : base(serviceProvider)
|
||||
public ServerEntryModelView(
|
||||
IServiceProvider serviceProvider,
|
||||
AuthService authService,
|
||||
ContentService contentService,
|
||||
CancellationService cancellationService,
|
||||
DebugService debugService,
|
||||
RunnerService runnerService
|
||||
) : base(serviceProvider)
|
||||
{
|
||||
_authService = authService;
|
||||
_contentService = contentService;
|
||||
_cancellationService = cancellationService;
|
||||
_debugService = debugService;
|
||||
_runnerService = runnerService;
|
||||
}
|
||||
|
||||
public void RunInstance()
|
||||
private Process? _process;
|
||||
|
||||
public async void RunInstance()
|
||||
{
|
||||
var p = Process.Start("./Nebula.Runner", "a b c");
|
||||
p.BeginOutputReadLine();
|
||||
p.BeginErrorReadLine();
|
||||
var authProv = _authService.SelectedAuth;
|
||||
|
||||
var buildInfo = await _contentService.GetBuildInfo(new RobustUrl(ServerHubInfo.Address), _cancellationService.Token);
|
||||
|
||||
await _runnerService.PrepareRun(buildInfo, _cancellationService.Token);
|
||||
|
||||
_process = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = "dotnet.exe",
|
||||
Arguments = "./Nebula.Runner.dll",
|
||||
Environment = {
|
||||
{ "ROBUST_AUTH_USERID", authProv?.UserId.ToString() } ,
|
||||
{ "ROBUST_AUTH_TOKEN", authProv?.Token.Token } ,
|
||||
{ "ROBUST_AUTH_SERVER", authProv?.AuthLoginPassword.AuthServer } ,
|
||||
{ "ROBUST_AUTH_PUBKEY", buildInfo.BuildInfo.Auth.PublicKey } ,
|
||||
{ "GAME_URL", ServerHubInfo.Address } ,
|
||||
{ "AUTH_LOGIN", authProv?.AuthLoginPassword.Login } ,
|
||||
},
|
||||
CreateNoWindow = true, UseShellExecute = false
|
||||
});
|
||||
|
||||
if (_process is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_process.OutputDataReceived += OnOutputDataReceived;
|
||||
_process.ErrorDataReceived += OnErrorDataReceived;
|
||||
|
||||
_process.Exited += OnExited;
|
||||
}
|
||||
|
||||
|
||||
private void OnExited(object? sender, EventArgs e)
|
||||
{
|
||||
if (_process is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_process.OutputDataReceived -= OnOutputDataReceived;
|
||||
_process.ErrorDataReceived -= OnErrorDataReceived;
|
||||
_process.Exited -= OnExited;
|
||||
|
||||
_debugService.Log("PROCESS EXIT WITH CODE " + _process.ExitCode);
|
||||
|
||||
_process.Dispose();
|
||||
_process = null;
|
||||
}
|
||||
|
||||
private void OnErrorDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (e.Data != null) _debugService.Error(e.Data);
|
||||
}
|
||||
|
||||
private void OnOutputDataReceived(object sender, DataReceivedEventArgs e)
|
||||
{
|
||||
if (e.Data != null) _debugService.Log(e.Data);
|
||||
}
|
||||
|
||||
|
||||
public void ReadLog()
|
||||
{
|
||||
@@ -36,6 +111,25 @@ public partial class ServerEntryModelView : ViewModelBase
|
||||
|
||||
public void StopInstance()
|
||||
{
|
||||
|
||||
_process?.Close();
|
||||
}
|
||||
|
||||
static string FindDotnetPath()
|
||||
{
|
||||
var pathEnv = Environment.GetEnvironmentVariable("PATH");
|
||||
var paths = pathEnv?.Split(System.IO.Path.PathSeparator);
|
||||
if (paths != null)
|
||||
{
|
||||
foreach (var path in paths)
|
||||
{
|
||||
var dotnetPath = System.IO.Path.Combine(path, "dotnet");
|
||||
if (System.IO.File.Exists(dotnetPath))
|
||||
{
|
||||
return dotnetPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Dotnet not found!");
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,57 @@
|
||||
using Nebula.Shared;
|
||||
using Nebula.Shared.Models;
|
||||
using Nebula.Shared.Services;
|
||||
using Nebula.Shared.Utils;
|
||||
using Robust.LoaderApi;
|
||||
|
||||
namespace Nebula.Runner;
|
||||
|
||||
[ServiceRegister]
|
||||
public class App(DebugService debugService)
|
||||
public sealed class App(DebugService debugService, RunnerService runnerService, ContentService contentService) : IRedialApi
|
||||
{
|
||||
|
||||
public void Run(string[] args)
|
||||
public async Task Run(string[] args1)
|
||||
{
|
||||
debugService.Log("HELLO!!! " + string.Join(" ",args));
|
||||
debugService.Log("HELLO!!! ");
|
||||
|
||||
var login = Environment.GetEnvironmentVariable("AUTH_LOGIN") ?? "Alexandra";
|
||||
var urlraw = Environment.GetEnvironmentVariable("GAME_URL") ?? "ss14://localhost";
|
||||
|
||||
var url = urlraw.ToRobustUrl();
|
||||
|
||||
using var cancelTokenSource = new CancellationTokenSource();
|
||||
var buildInfo = await contentService.GetBuildInfo(url, cancelTokenSource.Token);
|
||||
|
||||
|
||||
var args = new List<string>
|
||||
{
|
||||
// Pass username to launched client.
|
||||
// We don't load username from client_config.toml when launched via launcher.
|
||||
"--username", login,
|
||||
|
||||
// Tell game we are launcher
|
||||
"--cvar", "launch.launcher=true"
|
||||
};
|
||||
|
||||
var connectionString = url.ToString();
|
||||
if (!string.IsNullOrEmpty(buildInfo.BuildInfo.ConnectAddress))
|
||||
connectionString = buildInfo.BuildInfo.ConnectAddress;
|
||||
|
||||
// We are using the launcher. Don't show main menu etc..
|
||||
// Note: --launcher also implied --connect.
|
||||
// For this reason, content bundles do not set --launcher.
|
||||
args.Add("--launcher");
|
||||
|
||||
args.Add("--connect-address");
|
||||
args.Add(connectionString);
|
||||
|
||||
args.Add("--ss14-address");
|
||||
args.Add(url.ToString());
|
||||
|
||||
await runnerService.Run(args.ToArray(), buildInfo, this, cancelTokenSource.Token);
|
||||
}
|
||||
|
||||
public void Redial(Uri uri, string text = "")
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
@@ -12,6 +13,6 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.0" />
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.5-beta1"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Reflection;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Nebula.Shared;
|
||||
|
||||
@@ -11,6 +12,7 @@ public static class Program
|
||||
services.AddServices();
|
||||
|
||||
var serviceProvider = services.BuildServiceProvider();
|
||||
serviceProvider.GetService<App>()!.Run(args);
|
||||
var task = serviceProvider.GetService<App>()!.Run(args);
|
||||
task.Wait();
|
||||
}
|
||||
}
|
||||
@@ -8,12 +8,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Utils\runtime.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Utils\runtime.json">
|
||||
<LogicalName>Utility.runtime.json</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
|
||||
<PackageReference Include="libsodium" Version="1.0.20" />
|
||||
<PackageReference Include="Robust.Natives" Version="0.1.1" />
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.6" />
|
||||
</ItemGroup>
|
||||
|
||||
@@ -7,8 +7,17 @@ public static class ServiceExt
|
||||
{
|
||||
public static void AddServices(this IServiceCollection services)
|
||||
{
|
||||
foreach (var (type, inference) in GetServicesWithHelpAttribute(Assembly.GetExecutingAssembly()))
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
AddServices(services, assembly);
|
||||
}
|
||||
}
|
||||
|
||||
public static void AddServices(this IServiceCollection services, Assembly assembly)
|
||||
{
|
||||
foreach (var (type, inference) in GetServicesWithHelpAttribute(assembly))
|
||||
{
|
||||
Console.WriteLine("[ServiceMng] ADD SERVICE " + type);
|
||||
if (inference is null)
|
||||
{
|
||||
services.AddSingleton(type);
|
||||
|
||||
@@ -10,20 +10,36 @@ namespace Nebula.Shared.Services;
|
||||
[ServiceRegister]
|
||||
public class AssemblyService
|
||||
{
|
||||
private readonly Dictionary<string,Assembly> _assemblies = new();
|
||||
private readonly List<Assembly> _assemblies = new();
|
||||
private readonly DebugService _debugService;
|
||||
|
||||
public AssemblyService(DebugService debugService)
|
||||
{
|
||||
_debugService = debugService;
|
||||
|
||||
SharpZstd.Interop.ZstdImportResolver.ResolveLibrary += (name, assembly1, path) =>
|
||||
{
|
||||
if (name.Equals("SharpZstd.Native"))
|
||||
{
|
||||
_debugService.Debug("RESOLVING SHARPZSTD THINK: " + name + " " + path);
|
||||
GetRuntimeInfo(out string platform, out string architecture, out string extension);
|
||||
string fileName = GetDllName(platform, architecture, extension);
|
||||
|
||||
if (NativeLibrary.TryLoad(fileName, assembly1, path, out var nativeLibrary))
|
||||
{
|
||||
return nativeLibrary;
|
||||
}
|
||||
}
|
||||
return IntPtr.Zero;
|
||||
};
|
||||
}
|
||||
|
||||
//public IReadOnlyList<Assembly> Assemblies => _assemblies;
|
||||
public IReadOnlyList<Assembly> Assemblies => _assemblies;
|
||||
|
||||
public AssemblyApi Mount(IFileApi fileApi, string apiName = "")
|
||||
public AssemblyApi Mount(IFileApi fileApi)
|
||||
{
|
||||
var asmApi = new AssemblyApi(fileApi);
|
||||
AssemblyLoadContext.Default.Resolving += (context, name) => OnAssemblyResolving(context, name, asmApi, apiName);
|
||||
AssemblyLoadContext.Default.Resolving += (context, name) => OnAssemblyResolving(context, name, asmApi);
|
||||
AssemblyLoadContext.Default.ResolvingUnmanagedDll += LoadContextOnResolvingUnmanaged;
|
||||
|
||||
return asmApi;
|
||||
@@ -53,11 +69,6 @@ public class AssemblyService
|
||||
|
||||
public bool TryOpenAssembly(string name, AssemblyApi assemblyApi, [NotNullWhen(true)] out Assembly? assembly)
|
||||
{
|
||||
if (_assemblies.TryGetValue(name, out assembly))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TryOpenAssemblyStream(name, assemblyApi, out var asm, out var pdb))
|
||||
{
|
||||
assembly = null;
|
||||
@@ -66,8 +77,9 @@ public class AssemblyService
|
||||
|
||||
assembly = AssemblyLoadContext.Default.LoadFromStream(asm, pdb);
|
||||
_debugService.Log("LOADED ASSEMBLY " + name);
|
||||
|
||||
_assemblies.Add(name, assembly);
|
||||
|
||||
|
||||
if (!_assemblies.Contains(assembly)) _assemblies.Add(assembly);
|
||||
|
||||
asm.Dispose();
|
||||
pdb?.Dispose();
|
||||
@@ -86,13 +98,27 @@ public class AssemblyService
|
||||
assemblyApi.TryOpen($"{name}.pdb", out pdb);
|
||||
return true;
|
||||
}
|
||||
|
||||
private readonly HashSet<string> _resolvingAssemblies = new HashSet<string>();
|
||||
|
||||
private Assembly? OnAssemblyResolving(AssemblyLoadContext context, AssemblyName name, AssemblyApi assemblyApi,
|
||||
string apiName)
|
||||
private Assembly? OnAssemblyResolving(AssemblyLoadContext context, AssemblyName name, AssemblyApi assemblyApi)
|
||||
{
|
||||
|
||||
_debugService.Debug($"Resolving assembly from {apiName}: {name.Name}");
|
||||
return TryOpenAssembly(name.Name!, assemblyApi, out var assembly) ? assembly : null;
|
||||
if (_resolvingAssemblies.Contains(name.FullName))
|
||||
{
|
||||
_debugService.Debug($"Already resolving {name.Name}, skipping.");
|
||||
return null; // Prevent recursive resolution
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
_resolvingAssemblies.Add(name.FullName);
|
||||
_debugService.Debug($"Resolving assembly from FileAPI: {name.Name}");
|
||||
return TryOpenAssembly(name.Name!, assemblyApi, out var assembly) ? assembly : null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_resolvingAssemblies.Remove(name.FullName);
|
||||
}
|
||||
}
|
||||
|
||||
private IntPtr LoadContextOnResolvingUnmanaged(Assembly assembly, string unmanaged)
|
||||
@@ -104,7 +130,66 @@ public class AssemblyService
|
||||
|
||||
if (NativeLibrary.TryLoad(a, out var handle))
|
||||
return handle;
|
||||
|
||||
_debugService.Error("Loading dll error! Not found");
|
||||
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public static string GetDllName(
|
||||
string platform,
|
||||
string architecture,
|
||||
string extension)
|
||||
{
|
||||
string name = $"SharpZstd.Native.{extension}";
|
||||
return name;
|
||||
}
|
||||
|
||||
public static void GetRuntimeInfo(
|
||||
out string platform,
|
||||
out string architecture,
|
||||
out string extension)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
platform = "win";
|
||||
extension = "dll";
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
|
||||
{
|
||||
platform = "linux";
|
||||
extension = "so";
|
||||
}
|
||||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
|
||||
{
|
||||
platform = "osx";
|
||||
extension = "dylib";
|
||||
}
|
||||
else
|
||||
{
|
||||
platform = "linux";
|
||||
extension = "so";
|
||||
}
|
||||
|
||||
if (RuntimeInformation.ProcessArchitecture == Architecture.X64)
|
||||
{
|
||||
architecture = "x64";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.X86)
|
||||
{
|
||||
architecture = "x86";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm)
|
||||
{
|
||||
architecture = "arm";
|
||||
}
|
||||
else if (RuntimeInformation.ProcessArchitecture == Architecture.Arm64)
|
||||
{
|
||||
architecture = "arm64";
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException("Unsupported process architecture.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,6 +45,12 @@ public partial class AuthService(
|
||||
SelectedAuth = null;
|
||||
}
|
||||
|
||||
public void SetAuth(Guid guid, string token, string login, string authServer)
|
||||
{
|
||||
SelectedAuth = new CurrentAuthInfo(guid, new LoginToken(token, DateTimeOffset.Now),
|
||||
new AuthLoginPassword(login, "", authServer));
|
||||
}
|
||||
|
||||
public async Task<bool> EnsureToken()
|
||||
{
|
||||
if (SelectedAuth is null) return false;
|
||||
|
||||
@@ -81,7 +81,7 @@ public sealed class EngineService
|
||||
|
||||
try
|
||||
{
|
||||
return _assemblyService.Mount(_fileService.OpenZip(version, _fileService.EngineFileApi),$"Engine.Ensure-{version}");
|
||||
return _assemblyService.Mount(_fileService.OpenZip(version, _fileService.EngineFileApi));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -161,7 +161,7 @@ public sealed class EngineService
|
||||
|
||||
try
|
||||
{
|
||||
return _assemblyService.Mount(_fileService.OpenZip(fileName, _fileService.EngineFileApi),"Engine.EnsureModule");
|
||||
return _assemblyService.Mount(_fileService.OpenZip(fileName, _fileService.EngineFileApi));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
@@ -10,18 +10,8 @@ public sealed class RunnerService(
|
||||
ConfigurationService varService,
|
||||
FileService fileService,
|
||||
EngineService engineService,
|
||||
AssemblyService assemblyService,
|
||||
AuthService authService,
|
||||
PopupMessageService popupMessageService,
|
||||
CancellationService cancellationService)
|
||||
: IRedialApi
|
||||
AssemblyService assemblyService)
|
||||
{
|
||||
public async Task PrepareRun(RobustUrl url)
|
||||
{
|
||||
var buildInfo = await contentService.GetBuildInfo(url, cancellationService.Token);
|
||||
await PrepareRun(buildInfo, cancellationService.Token);
|
||||
}
|
||||
|
||||
public async Task PrepareRun(RobustBuildInfo buildInfo, CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Prepare Content!");
|
||||
@@ -67,60 +57,4 @@ public sealed class RunnerService(
|
||||
|
||||
await Task.Run(() => loader.Main(args), cancellationToken);
|
||||
}
|
||||
|
||||
public async Task RunGame(string urlraw)
|
||||
{
|
||||
var url = new RobustUrl(urlraw);
|
||||
|
||||
using var cancelTokenSource = new CancellationTokenSource();
|
||||
var buildInfo = await contentService.GetBuildInfo(url, cancelTokenSource.Token);
|
||||
|
||||
var account = authService.SelectedAuth;
|
||||
if (account is null)
|
||||
{
|
||||
popupMessageService.Popup("Error! Auth is required!");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buildInfo.BuildInfo.Auth.Mode != "Disabled")
|
||||
{
|
||||
Environment.SetEnvironmentVariable("ROBUST_AUTH_TOKEN", account.Token.Token);
|
||||
Environment.SetEnvironmentVariable("ROBUST_AUTH_USERID", account.UserId.ToString());
|
||||
Environment.SetEnvironmentVariable("ROBUST_AUTH_PUBKEY", buildInfo.BuildInfo.Auth.PublicKey);
|
||||
Environment.SetEnvironmentVariable("ROBUST_AUTH_SERVER", account.AuthLoginPassword.AuthServer);
|
||||
}
|
||||
|
||||
var args = new List<string>
|
||||
{
|
||||
// Pass username to launched client.
|
||||
// We don't load username from client_config.toml when launched via launcher.
|
||||
"--username", account.AuthLoginPassword.Login,
|
||||
|
||||
// Tell game we are launcher
|
||||
"--cvar", "launch.launcher=true"
|
||||
};
|
||||
|
||||
var connectionString = url.ToString();
|
||||
if (!string.IsNullOrEmpty(buildInfo.BuildInfo.ConnectAddress))
|
||||
connectionString = buildInfo.BuildInfo.ConnectAddress;
|
||||
|
||||
// We are using the launcher. Don't show main menu etc..
|
||||
// Note: --launcher also implied --connect.
|
||||
// For this reason, content bundles do not set --launcher.
|
||||
args.Add("--launcher");
|
||||
|
||||
args.Add("--connect-address");
|
||||
args.Add(connectionString);
|
||||
|
||||
args.Add("--ss14-address");
|
||||
args.Add(url.ToString());
|
||||
debugService.Debug("Connect to " + url.ToString() + " " + account.AuthLoginPassword.AuthServer);
|
||||
|
||||
await Run(args.ToArray(), buildInfo, this, cancelTokenSource.Token);
|
||||
}
|
||||
|
||||
public async void Redial(Uri uri, string text = "")
|
||||
{
|
||||
//await RunGame(uri.ToString());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user