diff --git a/Moonlight/App/Helpers/ParseHelper.cs b/Moonlight/App/Helpers/ParseHelper.cs index eddd4f2b..b3074c1c 100644 --- a/Moonlight/App/Helpers/ParseHelper.cs +++ b/Moonlight/App/Helpers/ParseHelper.cs @@ -37,4 +37,61 @@ public static class ParseHelper return res; } + + public static string GetHighestVersion(string[] versions) + { + // Initialize the highest version to the first version in the array + string highestVersion = versions[0]; + + // Loop through the remaining versions in the array + for (int i = 1; i < versions.Length; i++) + { + // Compare the current version to the highest version + if (CompareVersions(versions[i], highestVersion) > 0) + { + // If the current version is higher, update the highest version + highestVersion = versions[i]; + } + } + + return highestVersion; + } + + public static int CompareVersions(string version1, string version2) + { + // Split the versions into their component parts + string[] version1Parts = version1.Split('.'); + string[] version2Parts = version2.Split('.'); + + // Compare each component part in turn + for (int i = 0; i < version1Parts.Length && i < version2Parts.Length; i++) + { + int part1 = int.Parse(version1Parts[i]); + int part2 = int.Parse(version2Parts[i]); + + if (part1 < part2) + { + return -1; + } + else if (part1 > part2) + { + return 1; + } + } + + // If we get here, the versions are equal up to the length of the shorter one. + // If one version has more parts than the other, the longer one is considered higher. + if (version1Parts.Length < version2Parts.Length) + { + return -1; + } + else if (version1Parts.Length > version2Parts.Length) + { + return 1; + } + else + { + return 0; + } + } } \ No newline at end of file diff --git a/Moonlight/App/Services/FabricService.cs b/Moonlight/App/Services/FabricService.cs new file mode 100644 index 00000000..650ce155 --- /dev/null +++ b/Moonlight/App/Services/FabricService.cs @@ -0,0 +1,96 @@ +using System.Text; +using Moonlight.App.Helpers; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Moonlight.App.Services; + +public class FabricService +{ + private readonly HttpClient Client; + + public FabricService() + { + Client = new(); + } + + public async Task GetLatestInstallerVersion() + { + var data = await Client + .GetStringAsync("https://meta.fabricmc.net/v2/versions/installer"); + + var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); + + var stableVersions = new List(); + + foreach (var y in x) + { + var section = new ConfigurationBuilder().AddJsonStream( + new MemoryStream(Encoding.ASCII.GetBytes( + y.Root.ToString() + ) + ) + ).Build(); + + if (section.GetValue("stable")) + { + stableVersions.Add(section.GetValue("version")); + } + } + + return ParseHelper.GetHighestVersion(stableVersions.ToArray()); + } + + public async Task GetLatestLoaderVersion() + { + var data = await Client + .GetStringAsync("https://meta.fabricmc.net/v2/versions/loader"); + + var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); + + var stableVersions = new List(); + + foreach (var y in x) + { + var section = new ConfigurationBuilder().AddJsonStream( + new MemoryStream(Encoding.ASCII.GetBytes( + y.Root.ToString() + ) + ) + ).Build(); + + if (section.GetValue("stable")) + { + stableVersions.Add(section.GetValue("version")); + } + } + + return ParseHelper.GetHighestVersion(stableVersions.ToArray()); + } + public async Task GetGameVersions() + { + var data = await Client + .GetStringAsync("https://meta.fabricmc.net/v2/versions/game"); + + var x = JsonConvert.DeserializeObject(data) ?? Array.Empty(); + + var stableVersions = new List(); + + foreach (var y in x) + { + var section = new ConfigurationBuilder().AddJsonStream( + new MemoryStream(Encoding.ASCII.GetBytes( + y.Root.ToString() + ) + ) + ).Build(); + + if (section.GetValue("stable")) + { + stableVersions.Add(section.GetValue("version")); + } + } + + return stableVersions.ToArray(); + } +} \ No newline at end of file diff --git a/Moonlight/App/Services/ForgeService.cs b/Moonlight/App/Services/ForgeService.cs index ef23550f..6171ef44 100644 --- a/Moonlight/App/Services/ForgeService.cs +++ b/Moonlight/App/Services/ForgeService.cs @@ -15,12 +15,12 @@ public class ForgeService // Key: 1.9.4-recommended Value: 12.17.0.2317 public async Task> GetVersions() { - var data = await Client.GetAsync( + var data = await Client.GetStringAsync( "https://files.minecraftforge.net/net/minecraftforge/forge/promotions_slim.json"); var json = new ConfigurationBuilder().AddJsonStream( new MemoryStream(Encoding.ASCII.GetBytes( - await data.Content.ReadAsStringAsync() + data ) ) ).Build(); diff --git a/Moonlight/Program.cs b/Moonlight/Program.cs index 07aaa267..7621c7bf 100644 --- a/Moonlight/Program.cs +++ b/Moonlight/Program.cs @@ -107,6 +107,7 @@ namespace Moonlight builder.Services.AddSingleton(); builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); builder.Services.AddScoped(); diff --git a/Moonlight/Shared/Components/ServerControl/ServerSettings.razor b/Moonlight/Shared/Components/ServerControl/ServerSettings.razor index 8b575376..ee212b86 100644 --- a/Moonlight/Shared/Components/ServerControl/ServerSettings.razor +++ b/Moonlight/Shared/Components/ServerControl/ServerSettings.razor @@ -40,6 +40,9 @@ if(Tags.Contains("forgeversion")) Settings.Add("Forge version", typeof(ForgeVersionSetting)); + if(Tags.Contains("fabricversion")) + Settings.Add("Fabric version", typeof(FabricVersionSetting)); + if(Tags.Contains("join2start")) Settings.Add("Join2Start", typeof(Join2StartSetting)); diff --git a/Moonlight/Shared/Components/ServerControl/Settings/FabricVersionSetting.razor b/Moonlight/Shared/Components/ServerControl/Settings/FabricVersionSetting.razor new file mode 100644 index 00000000..0a22b159 --- /dev/null +++ b/Moonlight/Shared/Components/ServerControl/Settings/FabricVersionSetting.razor @@ -0,0 +1,173 @@ +@using Moonlight.App.Services +@using Microsoft.EntityFrameworkCore +@using Moonlight.App.Database.Entities +@using Moonlight.App.Repositories +@using Moonlight.App.Repositories.Servers +@using Moonlight.App.Helpers + +@inject ServerService ServerService +@inject ServerRepository ServerRepository +@inject ImageRepository ImageRepository +@inject FabricService FabricService +@inject SmartTranslateService TranslationService + +
+
+ + + + + + + + + + +
+
+ +@code +{ + [CascadingParameter] + public Server CurrentServer { get; set; } + + private string[] Versions = Array.Empty(); + private string CurrentVersion = ""; + + private string FabricVersion = ""; + private string LoaderVersion = ""; + + + private async Task Load(LazyLoader lazyLoader) + { + // Fabric version + + var fabricVersion = LiveMigrateVar( + "FABRIC_VERSION", + await FabricService.GetLatestInstallerVersion(), + true + ); + + FabricVersion = fabricVersion.Value; + + // Fabric loader version + + var loaderVersion = LiveMigrateVar( + "LOADER_VERSION", + await FabricService.GetLatestLoaderVersion(), + true + ); + + LoaderVersion = loaderVersion.Value; + + // Minecraft versions + + Versions = await FabricService.GetGameVersions(); + + var mcVersion = LiveMigrateVar( + "MC_VERSION", + Versions.First() + ); + + CurrentVersion = mcVersion.Value; + + await InvokeAsync(StateHasChanged); + } + + private ServerVariable LiveMigrateVar(string key, string value, bool overwrite = false) + { + var v = CurrentServer.Variables.FirstOrDefault(x => x.Key == key); + + if (v == null) + { + CurrentServer.Variables.Add(new() + { + Key = key, + Value = value + }); + + ServerRepository.Update(CurrentServer); + + return CurrentServer.Variables.First(x => x.Key == key); + } + else + { + if (string.IsNullOrEmpty(v.Value) || overwrite) + { + v.Value = value; + + ServerRepository.Update(CurrentServer); + } + + return v; + } + } + + private async Task Save() + { + var vars = CurrentServer.Variables; + var versionVar = vars.First(x => x.Key == "MC_VERSION"); + + versionVar.Value = CurrentVersion; + + // This searches for the display name of a version using the constructed full version + var version = ParseHelper.MinecraftToInt(CurrentVersion); + + var serverImage = ImageRepository + .Get() + .Include(x => x.DockerImages) + .First(x => x.Id == CurrentServer.Image.Id); + + var dockerImages = serverImage.DockerImages; + + var dockerImageToUpdate = dockerImages.Last(); + + if (version < 1130) + { + dockerImageToUpdate = dockerImages.First(x => x.Name.Contains("8")); + } + + if (version >= 1130) + { + dockerImageToUpdate = dockerImages.First(x => x.Name.Contains("11")); + } + + if (version >= 1170) + { + dockerImageToUpdate = dockerImages.First(x => x.Name.Contains("16")); + } + + if (version >= 1190) + { + dockerImageToUpdate = dockerImages.First(x => x.Name.Contains("17")); + } + + CurrentServer.DockerImageIndex = dockerImages.IndexOf(dockerImageToUpdate); + + ServerRepository.Update(CurrentServer); + + await ServerService.Reinstall(CurrentServer); + } +} \ No newline at end of file