diff --git a/Torch.API/ITorchBase.cs b/Torch.API/ITorchBase.cs index 9b1a335..33e4481 100644 --- a/Torch.API/ITorchBase.cs +++ b/Torch.API/ITorchBase.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using Torch.API.Managers; using Torch.API.Session; using VRage.Game.ModAPI; +using Version = SemanticVersioning.Version; namespace Torch.API { @@ -65,7 +66,7 @@ namespace Torch.API /// /// The binary version of the current instance. /// - InformationalVersion TorchVersion { get; } + Version TorchVersion { get; } /// /// Invoke an action on the game thread. diff --git a/Torch.API/InformationalVersion.cs b/Torch.API/InformationalVersion.cs deleted file mode 100644 index ef80213..0000000 --- a/Torch.API/InformationalVersion.cs +++ /dev/null @@ -1,62 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Torch.API -{ - /// - /// Version in the form v#.#.#.#-branch - /// - public class InformationalVersion - { - public Version Version { get; set; } - public string Branch { get; set; } - - public static bool TryParse(string input, out InformationalVersion version) - { - version = default(InformationalVersion); - var trim = input.TrimStart('v'); - var info = trim.Split(new[]{'-'}, 2); - if (!Version.TryParse(info[0], out Version result)) - return false; - - version = new InformationalVersion { Version = result }; - - if (info.Length > 1) - version.Branch = info[1]; - - return true; - } - - /// - public override string ToString() - { - if (Branch == null) - return $"v{Version}"; - - return $"v{Version}-{string.Join("-", Branch)}"; - } - - public static explicit operator InformationalVersion(Version v) - { - return new InformationalVersion { Version = v }; - } - - public static implicit operator Version(InformationalVersion v) - { - return v.Version; - } - - public static bool operator >(InformationalVersion lhs, InformationalVersion rhs) - { - return lhs.Version > rhs.Version; - } - - public static bool operator <(InformationalVersion lhs, InformationalVersion rhs) - { - return lhs.Version < rhs.Version; - } - } -} diff --git a/Torch.API/Torch.API.csproj b/Torch.API/Torch.API.csproj index d8cf975..a0335b4 100644 --- a/Torch.API/Torch.API.csproj +++ b/Torch.API/Torch.API.csproj @@ -20,6 +20,7 @@ + diff --git a/Torch.API/Utils/SemanticVersionConverter.cs b/Torch.API/Utils/SemanticVersionConverter.cs new file mode 100644 index 0000000..54ee9ca --- /dev/null +++ b/Torch.API/Utils/SemanticVersionConverter.cs @@ -0,0 +1,21 @@ +#nullable enable +using System; +using System.Text.Json; +using System.Text.Json.Serialization; +using Version = SemanticVersioning.Version; + +namespace Torch.API.Utils; + +public class SemanticVersionConverter : JsonConverter +{ + public override Version? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + Version.TryParse(reader.GetString(), out var ver); + return ver; + } + + public override void Write(Utf8JsonWriter writer, Version value, JsonSerializerOptions options) + { + writer.WriteStringValue(value.ToString()); + } +} \ No newline at end of file diff --git a/Torch.API/WebAPI/JenkinsQuery.cs b/Torch.API/WebAPI/JenkinsQuery.cs index 99886bd..a5be97f 100644 --- a/Torch.API/WebAPI/JenkinsQuery.cs +++ b/Torch.API/WebAPI/JenkinsQuery.cs @@ -4,10 +4,13 @@ using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Json; using System.Text; +using System.Text.Json.Serialization; using System.Threading.Tasks; -using Newtonsoft.Json; using NLog; +using Torch.API.Utils; +using Version = SemanticVersioning.Version; namespace Torch.API.WebAPI { @@ -20,7 +23,7 @@ namespace Torch.API.WebAPI private static readonly Logger Log = LogManager.GetCurrentClassLogger(); private static JenkinsQuery _instance; - public static JenkinsQuery Instance => _instance ?? (_instance = new JenkinsQuery()); + public static JenkinsQuery Instance => _instance ??= new JenkinsQuery(); private HttpClient _client; private JenkinsQuery() @@ -39,92 +42,43 @@ namespace Torch.API.WebAPI return null; } - string r = await h.Content.ReadAsStringAsync(); + var branchResponse = await h.Content.ReadFromJsonAsync(); - BranchResponse response; - try + if (branchResponse is null) { - response = JsonConvert.DeserializeObject(r); - } - catch (Exception ex) - { - Log.Error(ex, "Failed to deserialize branch response!"); + Log.Error("Error reading branch response"); return null; } + + h = await _client.GetAsync($"{branchResponse.LastStableBuild.Url}{API_PATH}"); + if (h.IsSuccessStatusCode) + return await h.Content.ReadFromJsonAsync(); + + Log.Error($"Job query failed with code {h.StatusCode}"); + return null; - h = await _client.GetAsync($"{response.LastStableBuild.URL}{API_PATH}"); - if (!h.IsSuccessStatusCode) - { - Log.Error($"Job query failed with code {h.StatusCode}"); - return null; - } - - r = await h.Content.ReadAsStringAsync(); - - Job job; - try - { - job = JsonConvert.DeserializeObject(r); - } - catch (Exception ex) - { - Log.Error(ex, "Failed to deserialize job response!"); - return null; - } - return job; } public async Task DownloadRelease(Job job, string path) { - var h = await _client.GetAsync(job.URL + ARTIFACT_PATH); + var h = await _client.GetAsync(job.Url + ARTIFACT_PATH); if (!h.IsSuccessStatusCode) { Log.Error($"Job download failed with code {h.StatusCode}"); return false; } var s = await h.Content.ReadAsStreamAsync(); - using (var fs = new FileStream(path, FileMode.Create)) - { - await s.CopyToAsync(fs); - await fs.FlushAsync(); - } + await using var fs = new FileStream(path, FileMode.Create); + await s.CopyToAsync(fs); return true; } } - public class BranchResponse - { - public string Name; - public string URL; - public Build LastBuild; - public Build LastStableBuild; - } + public record BranchResponse(string Name, string Url, Build LastBuild, Build LastStableBuild); - public class Build - { - public int Number; - public string URL; - } + public record Build(int Number, string Url); - public class Job - { - public int Number; - public bool Building; - public string Description; - public string Result; - public string URL; - private InformationalVersion _version; - - public InformationalVersion Version - { - get - { - if (_version == null) - InformationalVersion.TryParse(Description, out _version); - - return _version; - } - } - } + public record Job(int Number, bool Building, string Description, string Result, string Url, + [property: JsonConverter(typeof(SemanticVersionConverter))] Version Version); } diff --git a/Torch.API/WebAPI/PluginQuery.cs b/Torch.API/WebAPI/PluginQuery.cs index 3143f36..fe18347 100644 --- a/Torch.API/WebAPI/PluginQuery.cs +++ b/Torch.API/WebAPI/PluginQuery.cs @@ -14,7 +14,7 @@ namespace Torch.API.WebAPI public class PluginQuery { private const string ALL_QUERY = "https://torchapi.com/api/plugins/"; - private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/item/{0}/"; + private const string PLUGIN_QUERY = "https://torchapi.com/api/plugins/?guid={0}"; private readonly HttpClient _client; private static readonly Logger Log = LogManager.GetCurrentClassLogger(); @@ -42,15 +42,15 @@ namespace Torch.API.WebAPI CancellationToken.None); } - public async Task DownloadPlugin(Guid guid, string path = null) + public Task DownloadPlugin(Guid guid, string path = null) { - return await DownloadPlugin(guid.ToString(), path); + return DownloadPlugin(guid.ToString(), path); } public async Task DownloadPlugin(string guid, string path = null) { var item = await QueryOne(guid); - if (item == null) return false; + if (item is null) return false; return await DownloadPlugin(item, path); } @@ -59,14 +59,13 @@ namespace Torch.API.WebAPI try { path ??= Path.Combine(Directory.GetCurrentDirectory(), "Plugins", $"{item.Name}.zip"); - - var response = await QueryOne(item.Id); - if (response.Versions.Length == 0) + + if (item.Versions.Length == 0) { Log.Error($"Selected plugin {item.Name} does not have any versions to download!"); return false; } - var version = response.Versions.FirstOrDefault(v => v.Version == response.LatestVersion); + var version = item.Versions.FirstOrDefault(v => v.Version == item.LatestVersion); if (version is null) { Log.Error($"Could not find latest version for selected plugin {item.Name}"); diff --git a/Torch.Server/Initializer.cs b/Torch.Server/Initializer.cs index 062b63c..fa288f0 100644 --- a/Torch.Server/Initializer.cs +++ b/Torch.Server/Initializer.cs @@ -52,12 +52,8 @@ quit"; { if (_init) return false; - -#if !DEBUG + AppDomain.CurrentDomain.UnhandledException += HandleException; - LogManager.Configuration.AddRule(LogLevel.Info, LogLevel.Fatal, "console"); - LogManager.ReconfigExistingLoggers(); -#endif #if DEBUG //enables logging debug messages when built in debug mode. Amazing. @@ -232,16 +228,10 @@ quit"; private void HandleException(object sender, UnhandledExceptionEventArgs e) { _server.FatalException = true; + if (Debugger.IsAttached) + return; var ex = (Exception)e.ExceptionObject; Log.Fatal(ex.ToStringDemystified()); - if (MyFakes.ENABLE_MINIDUMP_SENDING) - { - string path = Path.Combine(MyFileSystem.UserDataPath, "Minidump.dmp"); - Log.Info($"Generating minidump at {path}"); - Log.Error("Keen broke the minidump, sorry."); - //MyMiniDump.Options options = MyMiniDump.Options.WithProcessThreadData | MyMiniDump.Options.WithThreadInfo; - //MyMiniDump.Write(path, options, MyMiniDump.ExceptionInfo.Present); - } LogManager.Flush(); if (Config.RestartOnCrash) { diff --git a/Torch.Server/Properties/launchSettings.json b/Torch.Server/Properties/launchSettings.json index 84581c4..8236f31 100644 --- a/Torch.Server/Properties/launchSettings.json +++ b/Torch.Server/Properties/launchSettings.json @@ -1,9 +1,9 @@ { - "$schema": "http://json.schemastore.org/launchsettings.json", + "$schema": "https://json.schemastore.org/launchsettings.json", "profiles": { "Torch.Server": { "commandName": "Project", - "commandLineArgs": "-noupdate", + "use64Bit": true, "hotReloadEnabled": false } diff --git a/Torch.Server/TorchServer.cs b/Torch.Server/TorchServer.cs index 0296fcc..2653ab1 100644 --- a/Torch.Server/TorchServer.cs +++ b/Torch.Server/TorchServer.cs @@ -207,13 +207,12 @@ namespace Torch.Server var config = (TorchConfig)torch.Config; LogManager.Flush(); - string exe = Assembly.GetExecutingAssembly().Location; - Debug.Assert(exe != null); - config.WaitForPID = Process.GetCurrentProcess().Id.ToString(); + string exe = Assembly.GetExecutingAssembly().Location.Replace("dll", "exe"); + config.WaitForPID = Environment.ProcessId.ToString(); config.TempAutostart = true; Process.Start(exe, config.ToString()); - Process.GetCurrentProcess().Kill(); + Environment.Exit(0); } } diff --git a/Torch/Managers/UpdateManager.cs b/Torch/Managers/UpdateManager.cs index 21b9327..5d7461f 100644 --- a/Torch/Managers/UpdateManager.cs +++ b/Torch/Managers/UpdateManager.cs @@ -50,7 +50,7 @@ namespace Torch.Managers try { - var job = await JenkinsQuery.Instance.GetLatestVersion(Torch.TorchVersion.Branch); + var job = await JenkinsQuery.Instance.GetLatestVersion(Torch.TorchVersion.Build); if (job == null) { _log.Info("Failed to fetch latest version."); diff --git a/Torch/TorchBase.cs b/Torch/TorchBase.cs index 67dcaed..e8f14ee 100644 --- a/Torch/TorchBase.cs +++ b/Torch/TorchBase.cs @@ -63,7 +63,7 @@ namespace Torch public ITorchConfig Config { get; protected set; } /// - public InformationalVersion TorchVersion { get; } + public SemanticVersioning.Version TorchVersion { get; } /// public Version GameVersion { get; private set; } @@ -115,16 +115,16 @@ namespace Torch #pragma warning restore CS0618 Config = config; - var versionString = Assembly.GetEntryAssembly() - .GetCustomAttribute() - .InformationalVersion; + var versionString = GetType().Assembly + .GetCustomAttribute()! + .InformationalVersion; - if (!InformationalVersion.TryParse(versionString, out InformationalVersion version)) + if (!SemanticVersioning.Version.TryParse(versionString, out var version)) throw new TypeLoadException("Unable to parse the Torch version from the assembly."); TorchVersion = version; - RunArgs = new string[0]; + RunArgs = Array.Empty(); Managers = new DependencyManager(); @@ -140,7 +140,7 @@ namespace Torch Managers.AddManager(sessionManager); Managers.AddManager(new PatchManager(this)); Managers.AddManager(new FilesystemManager(this)); - Managers.AddManager(new UpdateManager(this)); + // Managers.AddManager(new UpdateManager(this)); Managers.AddManager(new EventManager(this)); #pragma warning disable CS0618 Managers.AddManager(Plugins);