- tweak: fix resolving think

This commit is contained in:
2025-01-07 17:01:00 +03:00
parent 8619e248fd
commit 99312d38a8
12 changed files with 286 additions and 105 deletions

View File

@@ -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.");
}
}
}

View File

@@ -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;

View File

@@ -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)
{

View File

@@ -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());
}
}