- shit: Cleanup this mess
This commit is contained in:
@@ -4,22 +4,29 @@ namespace Nebula.Shared;
|
||||
|
||||
public static class CurrentConVar
|
||||
{
|
||||
public static readonly ConVar<string> EngineManifestUrl =
|
||||
public static readonly ConVar<string> EngineManifestUrl =
|
||||
ConVarBuilder.Build("engine.manifestUrl", "https://robust-builds.cdn.spacestation14.com/manifest.json");
|
||||
public static readonly ConVar<string> EngineModuleManifestUrl =
|
||||
|
||||
public static readonly ConVar<string> EngineModuleManifestUrl =
|
||||
ConVarBuilder.Build("engine.moduleManifestUrl", "https://robust-builds.cdn.spacestation14.com/modules.json");
|
||||
|
||||
public static readonly ConVar<int> ManifestDownloadProtocolVersion =
|
||||
ConVarBuilder.Build("engine.manifestDownloadProtocolVersion", 1);
|
||||
public static readonly ConVar<string> RobustAssemblyName =
|
||||
|
||||
public static readonly ConVar<string> RobustAssemblyName =
|
||||
ConVarBuilder.Build("engine.robustAssemblyName", "Robust.Client");
|
||||
|
||||
|
||||
public static readonly ConVar<string[]> Hub = ConVarBuilder.Build<string[]>("launcher.hub", [
|
||||
"https://hub.spacestation14.com/api/servers"
|
||||
]);
|
||||
|
||||
public static readonly ConVar<string[]> AuthServers = ConVarBuilder.Build<string[]>("launcher.authServers", [
|
||||
"https://auth.spacestation14.com/"
|
||||
]);
|
||||
|
||||
public static readonly ConVar<AuthLoginPassword[]> AuthProfiles = ConVarBuilder.Build<AuthLoginPassword[]>("auth.profiles", []);
|
||||
public static readonly ConVar<AuthLoginPassword> AuthCurrent = ConVarBuilder.Build<AuthLoginPassword>("auth.current");
|
||||
public static readonly ConVar<AuthLoginPassword[]> AuthProfiles =
|
||||
ConVarBuilder.Build<AuthLoginPassword[]>("auth.profiles", []);
|
||||
|
||||
public static readonly ConVar<AuthLoginPassword> AuthCurrent =
|
||||
ConVarBuilder.Build<AuthLoginPassword>("auth.current");
|
||||
}
|
||||
@@ -10,7 +10,7 @@ public class AssemblyApi : IFileApi
|
||||
{
|
||||
_root = root;
|
||||
}
|
||||
|
||||
|
||||
public bool TryOpen(string path, out Stream? stream)
|
||||
{
|
||||
return _root.TryOpen(path, out stream);
|
||||
|
||||
@@ -15,7 +15,6 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
{
|
||||
var fullPath = Path.Join(RootPath, path);
|
||||
if (File.Exists(fullPath))
|
||||
{
|
||||
try
|
||||
{
|
||||
stream = new FileStream(fullPath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
|
||||
@@ -26,7 +25,6 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
stream = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
stream = null;
|
||||
return false;
|
||||
@@ -66,6 +64,7 @@ public sealed class FileApi : IReadWriteFileApi
|
||||
{
|
||||
// Log exception if necessary
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ public interface ILoadingHandler
|
||||
{
|
||||
public void SetJobsCount(int count);
|
||||
public int GetJobsCount();
|
||||
|
||||
|
||||
public void SetResolvedJobsCount(int count);
|
||||
public int GetResolvedJobsCount();
|
||||
|
||||
@@ -30,7 +30,7 @@ public interface ILoadingHandler
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class QueryJob: IDisposable
|
||||
public sealed class QueryJob : IDisposable
|
||||
{
|
||||
private readonly ILoadingHandler _handler;
|
||||
|
||||
@@ -39,7 +39,7 @@ public sealed class QueryJob: IDisposable
|
||||
_handler = handler;
|
||||
handler.AppendJob();
|
||||
}
|
||||
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_handler.AppendResolvedJob();
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
namespace Nebula.Shared.Models;
|
||||
|
||||
public record ListItemTemplate(Type ModelType, string IconKey, string Label);
|
||||
@@ -4,18 +4,26 @@ namespace Nebula.Shared.Models;
|
||||
|
||||
public sealed record AuthInfo(
|
||||
[property: JsonPropertyName("mode")] string Mode,
|
||||
[property: JsonPropertyName("public_key")] string PublicKey);
|
||||
[property: JsonPropertyName("public_key")]
|
||||
string PublicKey);
|
||||
|
||||
public sealed record BuildInfo(
|
||||
[property: JsonPropertyName("engine_version")] string EngineVersion,
|
||||
[property: JsonPropertyName("fork_id")] string ForkId,
|
||||
[property: JsonPropertyName("version")] string Version,
|
||||
[property: JsonPropertyName("download_url")] string DownloadUrl,
|
||||
[property: JsonPropertyName("manifest_download_url")] string ManifestDownloadUrl,
|
||||
[property: JsonPropertyName("manifest_url")] string ManifestUrl,
|
||||
[property: JsonPropertyName("engine_version")]
|
||||
string EngineVersion,
|
||||
[property: JsonPropertyName("fork_id")]
|
||||
string ForkId,
|
||||
[property: JsonPropertyName("version")]
|
||||
string Version,
|
||||
[property: JsonPropertyName("download_url")]
|
||||
string DownloadUrl,
|
||||
[property: JsonPropertyName("manifest_download_url")]
|
||||
string ManifestDownloadUrl,
|
||||
[property: JsonPropertyName("manifest_url")]
|
||||
string ManifestUrl,
|
||||
[property: JsonPropertyName("acz")] bool Acz,
|
||||
[property: JsonPropertyName("hash")] string Hash,
|
||||
[property: JsonPropertyName("manifest_hash")] string ManifestHash);
|
||||
[property: JsonPropertyName("manifest_hash")]
|
||||
string ManifestHash);
|
||||
|
||||
public sealed record ServerLink(
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
@@ -23,16 +31,20 @@ public sealed record ServerLink(
|
||||
[property: JsonPropertyName("url")] string Url);
|
||||
|
||||
public sealed record ServerInfo(
|
||||
[property: JsonPropertyName("connect_address")] string ConnectAddress,
|
||||
[property: JsonPropertyName("connect_address")]
|
||||
string ConnectAddress,
|
||||
[property: JsonPropertyName("auth")] AuthInfo Auth,
|
||||
[property: JsonPropertyName("build")] BuildInfo Build,
|
||||
[property: JsonPropertyName("desc")] string Desc,
|
||||
[property: JsonPropertyName("links")] List<ServerLink> Links);
|
||||
|
||||
public sealed record EngineVersionInfo(
|
||||
[property: JsonPropertyName("insecure")] bool Insecure,
|
||||
[property: JsonPropertyName("redirect")] string? RedirectVersion,
|
||||
[property: JsonPropertyName("platforms")] Dictionary<string, EngineBuildInfo> Platforms);
|
||||
[property: JsonPropertyName("insecure")]
|
||||
bool Insecure,
|
||||
[property: JsonPropertyName("redirect")]
|
||||
string? RedirectVersion,
|
||||
[property: JsonPropertyName("platforms")]
|
||||
Dictionary<string, EngineBuildInfo> Platforms);
|
||||
|
||||
public sealed class EngineBuildInfo
|
||||
{
|
||||
@@ -47,27 +59,39 @@ public sealed class EngineBuildInfo
|
||||
}
|
||||
|
||||
public sealed record ServerHubInfo(
|
||||
[property: JsonPropertyName("address")] string Address,
|
||||
[property: JsonPropertyName("statusData")] ServerStatus StatusData,
|
||||
[property: JsonPropertyName("inferredTags")] List<string> InferredTags);
|
||||
[property: JsonPropertyName("address")]
|
||||
string Address,
|
||||
[property: JsonPropertyName("statusData")]
|
||||
ServerStatus StatusData,
|
||||
[property: JsonPropertyName("inferredTags")]
|
||||
List<string> InferredTags);
|
||||
|
||||
public sealed record ServerStatus(
|
||||
[property: JsonPropertyName("map")] string Map,
|
||||
[property: JsonPropertyName("name")] string Name,
|
||||
[property: JsonPropertyName("tags")] List<string> Tags,
|
||||
[property: JsonPropertyName("preset")] string Preset,
|
||||
[property: JsonPropertyName("players")] int Players,
|
||||
[property: JsonPropertyName("round_id")] int RoundId,
|
||||
[property: JsonPropertyName("run_level")] int RunLevel,
|
||||
[property: JsonPropertyName("panic_bunker")] bool PanicBunker,
|
||||
[property: JsonPropertyName("round_start_time")] DateTime? RoundStartTime,
|
||||
[property: JsonPropertyName("soft_max_players")] int SoftMaxPlayers);
|
||||
[property: JsonPropertyName("players")]
|
||||
int Players,
|
||||
[property: JsonPropertyName("round_id")]
|
||||
int RoundId,
|
||||
[property: JsonPropertyName("run_level")]
|
||||
int RunLevel,
|
||||
[property: JsonPropertyName("panic_bunker")]
|
||||
bool PanicBunker,
|
||||
[property: JsonPropertyName("round_start_time")]
|
||||
DateTime? RoundStartTime,
|
||||
[property: JsonPropertyName("soft_max_players")]
|
||||
int SoftMaxPlayers);
|
||||
|
||||
public sealed record ModulesInfo(
|
||||
[property: JsonPropertyName("modules")] Dictionary<string, Module> Modules);
|
||||
[property: JsonPropertyName("modules")]
|
||||
Dictionary<string, Module> Modules);
|
||||
|
||||
public sealed record Module(
|
||||
[property: JsonPropertyName("versions")] Dictionary<string, ModuleVersionInfo> Versions);
|
||||
[property: JsonPropertyName("versions")]
|
||||
Dictionary<string, ModuleVersionInfo> Versions);
|
||||
|
||||
public sealed record ModuleVersionInfo(
|
||||
[property: JsonPropertyName("platforms")] Dictionary<string, EngineBuildInfo> Platforms);
|
||||
[property: JsonPropertyName("platforms")]
|
||||
Dictionary<string, EngineBuildInfo> Platforms);
|
||||
@@ -11,13 +11,14 @@
|
||||
<EmbeddedResource Include="Utils\runtime.json">
|
||||
<LogicalName>Utility.runtime.json</LogicalName>
|
||||
</EmbeddedResource>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0" />
|
||||
<PackageReference Include="Robust.Natives" Version="0.1.1" />
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.6" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="9.0.0"/>
|
||||
<PackageReference Include="Robust.Natives" Version="0.1.1"/>
|
||||
<PackageReference Include="SharpZstd.Interop" Version="1.5.6"/>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj" />
|
||||
<ProjectReference Include="..\Nebula.SourceGenerators\Nebula.SourceGenerators.csproj" OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
|
||||
<ProjectReference Include="..\Robust.LoaderApi\Robust.LoaderApi\Robust.LoaderApi.csproj"/>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -7,47 +7,39 @@ public static class ServiceExt
|
||||
{
|
||||
public static void AddServices(this IServiceCollection services)
|
||||
{
|
||||
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
|
||||
{
|
||||
AddServices(services, assembly);
|
||||
}
|
||||
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);
|
||||
}
|
||||
else
|
||||
{
|
||||
services.AddSingleton(inference, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static IEnumerable<(Type,Type?)> GetServicesWithHelpAttribute(Assembly assembly) {
|
||||
foreach(Type type in assembly.GetTypes())
|
||||
|
||||
private static IEnumerable<(Type, Type?)> GetServicesWithHelpAttribute(Assembly assembly)
|
||||
{
|
||||
foreach (var type in assembly.GetTypes())
|
||||
{
|
||||
var attr = type.GetCustomAttribute<ServiceRegisterAttribute>();
|
||||
if (attr is not null) {
|
||||
yield return (type, attr.Inference);
|
||||
}
|
||||
if (attr is not null) yield return (type, attr.Inference);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ServiceRegisterAttribute : Attribute
|
||||
{
|
||||
public Type? Inference { get; }
|
||||
public bool IsSingleton { get; }
|
||||
|
||||
public ServiceRegisterAttribute(Type? inference = null, bool isSingleton = true)
|
||||
{
|
||||
IsSingleton = isSingleton;
|
||||
Inference = inference;
|
||||
}
|
||||
|
||||
public Type? Inference { get; }
|
||||
public bool IsSingleton { get; }
|
||||
}
|
||||
@@ -4,6 +4,7 @@ using System.Runtime.InteropServices;
|
||||
using System.Runtime.Loader;
|
||||
using Nebula.Shared.FileApis;
|
||||
using Robust.LoaderApi;
|
||||
using SharpZstd.Interop;
|
||||
|
||||
namespace Nebula.Shared.Services;
|
||||
|
||||
@@ -13,23 +14,23 @@ public class AssemblyService
|
||||
private readonly List<Assembly> _assemblies = new();
|
||||
private readonly DebugService _debugService;
|
||||
|
||||
private readonly HashSet<string> _resolvingAssemblies = new();
|
||||
|
||||
public AssemblyService(DebugService debugService)
|
||||
{
|
||||
_debugService = debugService;
|
||||
|
||||
SharpZstd.Interop.ZstdImportResolver.ResolveLibrary += (name, assembly1, path) =>
|
||||
|
||||
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);
|
||||
GetRuntimeInfo(out var platform, out var architecture, out var extension);
|
||||
var fileName = GetDllName(platform, architecture, extension);
|
||||
|
||||
if (NativeLibrary.TryLoad(fileName, assembly1, path, out var nativeLibrary))
|
||||
{
|
||||
return nativeLibrary;
|
||||
}
|
||||
if (NativeLibrary.TryLoad(fileName, assembly1, path, out var nativeLibrary)) return nativeLibrary;
|
||||
}
|
||||
|
||||
return IntPtr.Zero;
|
||||
};
|
||||
}
|
||||
@@ -98,8 +99,6 @@ 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)
|
||||
{
|
||||
@@ -108,7 +107,7 @@ public class AssemblyService
|
||||
_debugService.Debug($"Already resolving {name.Name}, skipping.");
|
||||
return null; // Prevent recursive resolution
|
||||
}
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
_resolvingAssemblies.Add(name.FullName);
|
||||
@@ -130,18 +129,18 @@ 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}";
|
||||
var name = $"SharpZstd.Native.{extension}";
|
||||
return name;
|
||||
}
|
||||
|
||||
@@ -172,24 +171,14 @@ public class AssemblyService
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4,37 +4,37 @@ using Nebula.Shared.Models.Auth;
|
||||
namespace Nebula.Shared.Services;
|
||||
|
||||
[ServiceRegister]
|
||||
public partial class AuthService(
|
||||
RestService restService,
|
||||
DebugService debugService,
|
||||
public class AuthService(
|
||||
RestService restService,
|
||||
DebugService debugService,
|
||||
CancellationService cancellationService)
|
||||
{
|
||||
private readonly HttpClient _httpClient = new();
|
||||
public CurrentAuthInfo? SelectedAuth { get; internal set; }
|
||||
|
||||
public string Reason = "";
|
||||
public CurrentAuthInfo? SelectedAuth { get; internal set; }
|
||||
|
||||
public async Task<bool> Auth(AuthLoginPassword authLoginPassword)
|
||||
{
|
||||
var authServer = authLoginPassword.AuthServer;
|
||||
var login = authLoginPassword.Login;
|
||||
var password = authLoginPassword.Password;
|
||||
|
||||
|
||||
debugService.Debug($"Auth to {authServer}api/auth/authenticate {login}");
|
||||
|
||||
|
||||
var authUrl = new Uri($"{authServer}api/auth/authenticate");
|
||||
|
||||
var result =
|
||||
await restService.PostAsync<AuthenticateResponse, AuthenticateRequest>(
|
||||
new AuthenticateRequest(login, password), authUrl, cancellationService.Token);
|
||||
|
||||
|
||||
if (result.Value is null)
|
||||
{
|
||||
Reason = result.Message;
|
||||
return false;
|
||||
}
|
||||
|
||||
SelectedAuth = new CurrentAuthInfo(result.Value.UserId,
|
||||
SelectedAuth = new CurrentAuthInfo(result.Value.UserId,
|
||||
new LoginToken(result.Value.Token, result.Value.ExpireTime), authLoginPassword);
|
||||
|
||||
return true;
|
||||
@@ -68,4 +68,5 @@ public partial class AuthService(
|
||||
}
|
||||
|
||||
public sealed record CurrentAuthInfo(Guid UserId, LoginToken Token, AuthLoginPassword AuthLoginPassword);
|
||||
public record AuthLoginPassword(string Login, string Password, string AuthServer);
|
||||
|
||||
public record AuthLoginPassword(string Login, string Password, string AuthServer);
|
||||
@@ -5,15 +5,15 @@ namespace Nebula.Shared.Services;
|
||||
|
||||
public class ConVar<T>
|
||||
{
|
||||
public string Name { get; }
|
||||
public Type Type => typeof(T);
|
||||
public T? DefaultValue { get; }
|
||||
|
||||
public ConVar(string name, T? defaultValue = default)
|
||||
{
|
||||
Name = name ?? throw new ArgumentNullException(nameof(name));
|
||||
DefaultValue = defaultValue;
|
||||
}
|
||||
|
||||
public string Name { get; }
|
||||
public Type Type => typeof(T);
|
||||
public T? DefaultValue { get; }
|
||||
}
|
||||
|
||||
public static class ConVarBuilder
|
||||
@@ -30,8 +30,8 @@ public static class ConVarBuilder
|
||||
[ServiceRegister]
|
||||
public class ConfigurationService
|
||||
{
|
||||
private readonly FileService _fileService;
|
||||
private readonly DebugService _debugService;
|
||||
private readonly FileService _fileService;
|
||||
|
||||
public ConfigurationService(FileService fileService, DebugService debugService)
|
||||
{
|
||||
@@ -46,7 +46,6 @@ public class ConfigurationService
|
||||
try
|
||||
{
|
||||
if (_fileService.ConfigurationApi.TryOpen(GetFileName(conVar), out var stream))
|
||||
{
|
||||
using (stream)
|
||||
{
|
||||
var obj = JsonSerializer.Deserialize<T>(stream);
|
||||
@@ -56,7 +55,6 @@ public class ConfigurationService
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -71,10 +69,11 @@ public class ConfigurationService
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(conVar);
|
||||
if (value == null) throw new ArgumentNullException(nameof(value));
|
||||
|
||||
|
||||
if (!conVar.Type.IsInstanceOfType(value))
|
||||
{
|
||||
_debugService.Error($"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}.");
|
||||
_debugService.Error(
|
||||
$"Type mismatch for config {conVar.Name}. Expected {conVar.Type}, got {value.GetType()}.");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -105,7 +104,8 @@ public class ConfigurationService
|
||||
|
||||
public static class ConfigExtensions
|
||||
{
|
||||
public static bool TryGetConfigValue<T>(this ConfigurationService configurationService, ConVar<T> conVar, [NotNullWhen(true)] out T? value)
|
||||
public static bool TryGetConfigValue<T>(this ConfigurationService configurationService, ConVar<T> conVar,
|
||||
[NotNullWhen(true)] out T? value)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(configurationService);
|
||||
ArgumentNullException.ThrowIfNull(conVar);
|
||||
|
||||
@@ -15,7 +15,8 @@ public partial class ContentService
|
||||
return fileService.ContentFileApi.Has(item.Hash);
|
||||
}
|
||||
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri, ILoadingHandler loadingHandler,
|
||||
public async Task<List<RobustManifestItem>> EnsureItems(ManifestReader manifestReader, Uri downloadUri,
|
||||
ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
List<RobustManifestItem> allItems = [];
|
||||
@@ -66,7 +67,8 @@ public partial class ContentService
|
||||
return await EnsureItems(manifestReader, info.DownloadUri, loadingHandler, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task Unpack(RobustManifestInfo info, IWriteFileApi otherApi, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task Unpack(RobustManifestInfo info, IWriteFileApi otherApi, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Unpack manifest files");
|
||||
var items = await EnsureItems(info, loadingHandler, cancellationToken);
|
||||
@@ -83,11 +85,13 @@ public partial class ContentService
|
||||
{
|
||||
debugService.Error("OH FUCK!! " + item.Path);
|
||||
}
|
||||
|
||||
loadingHandler.AppendResolvedJob();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task Download(Uri contentCdn, List<RobustManifestItem> toDownload, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
if (toDownload.Count == 0 || cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
@@ -110,7 +114,8 @@ public partial class ContentService
|
||||
var request = new HttpRequestMessage(HttpMethod.Post, contentCdn);
|
||||
request.Headers.Add(
|
||||
"X-Robust-Download-Protocol",
|
||||
varService.GetConfigValue(CurrentConVar.ManifestDownloadProtocolVersion).ToString(CultureInfo.InvariantCulture));
|
||||
varService.GetConfigValue(CurrentConVar.ManifestDownloadProtocolVersion)
|
||||
.ToString(CultureInfo.InvariantCulture));
|
||||
|
||||
request.Content = new ByteArrayContent(requestBody);
|
||||
request.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
|
||||
@@ -123,7 +128,7 @@ public partial class ContentService
|
||||
debugService.Log("Downloading is cancelled!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
downloadJobWatch.Dispose();
|
||||
|
||||
response.EnsureSuccessStatusCode();
|
||||
@@ -163,9 +168,9 @@ public partial class ContentService
|
||||
var readBuffer = new byte[1024];
|
||||
|
||||
var i = 0;
|
||||
|
||||
|
||||
loadingHandler.AppendJob(toDownload.Count);
|
||||
|
||||
|
||||
foreach (var item in toDownload)
|
||||
{
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
|
||||
@@ -5,20 +5,19 @@ namespace Nebula.Shared.Services;
|
||||
[ServiceRegister]
|
||||
public class DebugService : IDisposable
|
||||
{
|
||||
public ILogger Logger;
|
||||
|
||||
private static string LogPath = Path.Combine(FileService.RootPath, "log");
|
||||
public DateTime LogDate = DateTime.Now;
|
||||
public ILogger Logger;
|
||||
private FileStream LogStream;
|
||||
private StreamWriter LogWriter;
|
||||
|
||||
public DebugService(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
|
||||
|
||||
//if (!Directory.Exists(LogPath))
|
||||
// Directory.CreateDirectory(LogPath);
|
||||
|
||||
// Directory.CreateDirectory(LogPath);
|
||||
|
||||
//var filename = String.Format("{0:yyyy-MM-dd}.txt", DateTime.Now);
|
||||
|
||||
//LogStream = File.Open(Path.Combine(LogPath, filename),
|
||||
@@ -26,6 +25,12 @@ public class DebugService : IDisposable
|
||||
//LogWriter = new StreamWriter(LogStream);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogWriter.Dispose();
|
||||
LogStream.Dispose();
|
||||
}
|
||||
|
||||
public void Debug(string message)
|
||||
{
|
||||
Log(LoggerCategory.Debug, message);
|
||||
@@ -44,16 +49,10 @@ public class DebugService : IDisposable
|
||||
public void Error(Exception e)
|
||||
{
|
||||
Error(e.Message + "\r\n" + e.StackTrace);
|
||||
if(e.InnerException != null)
|
||||
if (e.InnerException != null)
|
||||
Error(e.InnerException);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
LogWriter.Dispose();
|
||||
LogStream.Dispose();
|
||||
}
|
||||
|
||||
private void Log(LoggerCategory category, string message)
|
||||
{
|
||||
Logger.Log(category, message);
|
||||
|
||||
@@ -14,12 +14,12 @@ public sealed class EngineService
|
||||
private readonly RestService _restService;
|
||||
private readonly IServiceProvider _serviceProvider;
|
||||
private readonly ConfigurationService _varService;
|
||||
|
||||
|
||||
private readonly Task _currInfoTask;
|
||||
|
||||
public Dictionary<string, Module> ModuleInfos = default!;
|
||||
public Dictionary<string, EngineVersionInfo> VersionInfos = default!;
|
||||
|
||||
private Task _currInfoTask;
|
||||
|
||||
public EngineService(RestService restService, DebugService debugService, ConfigurationService varService,
|
||||
FileService fileService, IServiceProvider serviceProvider, AssemblyService assemblyService)
|
||||
{
|
||||
@@ -52,7 +52,7 @@ public sealed class EngineService
|
||||
public EngineBuildInfo? GetVersionInfo(string version)
|
||||
{
|
||||
CheckAndWaitValidation();
|
||||
|
||||
|
||||
if (!VersionInfos.TryGetValue(version, out var foundVersion))
|
||||
return null;
|
||||
|
||||
@@ -120,7 +120,7 @@ public sealed class EngineService
|
||||
public EngineBuildInfo? GetModuleBuildInfo(string moduleName, string version)
|
||||
{
|
||||
CheckAndWaitValidation();
|
||||
|
||||
|
||||
if (!ModuleInfos.TryGetValue(moduleName, out var module) ||
|
||||
!module.Versions.TryGetValue(version, out var value))
|
||||
return null;
|
||||
@@ -140,7 +140,7 @@ public sealed class EngineService
|
||||
public string ResolveModuleVersion(string moduleName, string engineVersion)
|
||||
{
|
||||
CheckAndWaitValidation();
|
||||
|
||||
|
||||
var engineVersionObj = Version.Parse(engineVersion);
|
||||
var module = ModuleInfos[moduleName];
|
||||
var selectedVersion = module.Versions.Select(kv => new { Version = Version.Parse(kv.Key), kv.Key, kv.Value })
|
||||
@@ -192,9 +192,9 @@ public sealed class EngineService
|
||||
|
||||
private void CheckAndWaitValidation()
|
||||
{
|
||||
if (_currInfoTask.IsCompleted)
|
||||
if (_currInfoTask.IsCompleted)
|
||||
return;
|
||||
|
||||
|
||||
_debugService.Debug("thinks is not done yet, please wait");
|
||||
_currInfoTask.Wait();
|
||||
}
|
||||
|
||||
@@ -14,12 +14,12 @@ public class FileService
|
||||
Environment.SpecialFolder.ApplicationData), "Datum");
|
||||
|
||||
private readonly DebugService _debugService;
|
||||
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
|
||||
public readonly IReadWriteFileApi ContentFileApi;
|
||||
public readonly IReadWriteFileApi EngineFileApi;
|
||||
public readonly IReadWriteFileApi ManifestFileApi;
|
||||
public readonly IReadWriteFileApi ConfigurationApi;
|
||||
|
||||
|
||||
private HashApi? _hashApi;
|
||||
|
||||
public FileService(DebugService debugService)
|
||||
|
||||
@@ -8,43 +8,43 @@ public class HubService
|
||||
private readonly ConfigurationService _configurationService;
|
||||
private readonly RestService _restService;
|
||||
|
||||
private readonly List<ServerHubInfo> _serverList = new();
|
||||
|
||||
public Action<HubServerChangedEventArgs>? HubServerChangedEventArgs;
|
||||
public Action? HubServerLoaded;
|
||||
|
||||
private readonly List<ServerHubInfo> _serverList = new();
|
||||
public IReadOnlyList<ServerHubInfo> ServerList => _serverList;
|
||||
|
||||
private bool _isUpdating = false;
|
||||
public bool IsUpdating => _isUpdating;
|
||||
public HubService(ConfigurationService configurationService, RestService restService)
|
||||
{
|
||||
_configurationService = configurationService;
|
||||
_restService = restService;
|
||||
|
||||
|
||||
UpdateHub();
|
||||
}
|
||||
|
||||
public IReadOnlyList<ServerHubInfo> ServerList => _serverList;
|
||||
public bool IsUpdating { get; private set; }
|
||||
|
||||
public async void UpdateHub()
|
||||
{
|
||||
if(_isUpdating) return;
|
||||
|
||||
if (IsUpdating) return;
|
||||
|
||||
_serverList.Clear();
|
||||
|
||||
_isUpdating = true;
|
||||
|
||||
IsUpdating = true;
|
||||
|
||||
HubServerChangedEventArgs?.Invoke(new HubServerChangedEventArgs([], HubServerChangeAction.Clear));
|
||||
|
||||
|
||||
foreach (var urlStr in _configurationService.GetConfigValue(CurrentConVar.Hub)!)
|
||||
{
|
||||
var servers = await _restService.GetAsyncDefault<List<ServerHubInfo>>(new Uri(urlStr), [], CancellationToken.None);
|
||||
var servers =
|
||||
await _restService.GetAsyncDefault<List<ServerHubInfo>>(new Uri(urlStr), [], CancellationToken.None);
|
||||
_serverList.AddRange(servers);
|
||||
HubServerChangedEventArgs?.Invoke(new HubServerChangedEventArgs(servers, HubServerChangeAction.Add));
|
||||
}
|
||||
|
||||
_isUpdating = false;
|
||||
|
||||
IsUpdating = false;
|
||||
HubServerLoaded?.Invoke();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public class HubServerChangedEventArgs : EventArgs
|
||||
@@ -61,5 +61,7 @@ public class HubServerChangedEventArgs : EventArgs
|
||||
|
||||
public enum HubServerChangeAction
|
||||
{
|
||||
Add, Remove, Clear,
|
||||
Add,
|
||||
Remove,
|
||||
Clear
|
||||
}
|
||||
@@ -3,12 +3,14 @@ namespace Nebula.Shared.Services;
|
||||
[ServiceRegister]
|
||||
public class PopupMessageService
|
||||
{
|
||||
public Action<object>? OnPopupRequired;
|
||||
public Action<object>? OnCloseRequired;
|
||||
public Action<object>? OnPopupRequired;
|
||||
|
||||
public void Popup(object obj)
|
||||
{
|
||||
OnPopupRequired?.Invoke(obj);
|
||||
}
|
||||
|
||||
public void ClosePopup(object obj)
|
||||
{
|
||||
OnCloseRequired?.Invoke(obj);
|
||||
|
||||
@@ -12,7 +12,8 @@ public sealed class RunnerService(
|
||||
EngineService engineService,
|
||||
AssemblyService assemblyService)
|
||||
{
|
||||
public async Task PrepareRun(RobustBuildInfo buildInfo, ILoadingHandler loadingHandler, CancellationToken cancellationToken)
|
||||
public async Task PrepareRun(RobustBuildInfo buildInfo, ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Prepare Content!");
|
||||
|
||||
@@ -20,12 +21,13 @@ public sealed class RunnerService(
|
||||
|
||||
if (engine is null)
|
||||
throw new Exception("Engine version is not usable: " + buildInfo.BuildInfo.Build.EngineVersion);
|
||||
|
||||
|
||||
await contentService.EnsureItems(buildInfo.RobustManifestInfo, loadingHandler, cancellationToken);
|
||||
await engineService.EnsureEngineModules("Robust.Client.WebView", buildInfo.BuildInfo.Build.EngineVersion);
|
||||
}
|
||||
|
||||
public async Task Run(string[] runArgs, RobustBuildInfo buildInfo, IRedialApi redialApi, ILoadingHandler loadingHandler,
|
||||
public async Task Run(string[] runArgs, RobustBuildInfo buildInfo, IRedialApi redialApi,
|
||||
ILoadingHandler loadingHandler,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
debugService.Log("Start Content!");
|
||||
@@ -49,7 +51,8 @@ public sealed class RunnerService(
|
||||
|
||||
var args = new MainArgs(runArgs, engine, redialApi, extraMounts);
|
||||
|
||||
if (!assemblyService.TryOpenAssembly(varService.GetConfigValue(CurrentConVar.RobustAssemblyName)!, engine, out var clientAssembly))
|
||||
if (!assemblyService.TryOpenAssembly(varService.GetConfigValue(CurrentConVar.RobustAssemblyName)!, engine,
|
||||
out var clientAssembly))
|
||||
throw new Exception("Unable to locate Robust.Client.dll in engine build!");
|
||||
|
||||
if (!assemblyService.TryGetLoader(clientAssembly, out var loader))
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Nebula.Shared.Utils;
|
||||
public static class Helper
|
||||
{
|
||||
public static readonly JsonSerializerOptions JsonWebOptions = new(JsonSerializerDefaults.Web);
|
||||
|
||||
|
||||
public static void OpenBrowser(string url)
|
||||
{
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
@@ -22,12 +22,8 @@ public static class Helper
|
||||
{
|
||||
Process.Start("open", url);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static async Task<T> AsJson<T>(this HttpContent content) where T : notnull
|
||||
{
|
||||
var str = await content.ReadAsStringAsync();
|
||||
|
||||
@@ -121,7 +121,7 @@ public static class UriHelper
|
||||
{
|
||||
return new Uri(GetServerApiAddress(serverAddress), "client.zip");
|
||||
}
|
||||
|
||||
|
||||
[Pure]
|
||||
public static Uri AddParameter(this Uri url, string paramName, string paramValue)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user