using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Text; using System.Text.Json; using System.Threading.Tasks; namespace VeloeMinecraftLauncher.MinecraftLauncher; internal static class StartCommandBuilder { public static string Build(Entity.Version.Version version, string username) { var returnString = new StringBuilder(); char separator = ':'; if (OperatingSystem.IsWindows()) separator = ';'; if (version is null) return returnString.ToString(); // setting natives folder if (version.InheritsFrom is null) returnString.Append($"-Djava.library.path={Settings.MinecraftForlderPath + "versions/" + version.Id + "/natives/"}"); else returnString.Append($"-Djava.library.path={Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/natives/"}"); //for forge, vanilla optifine, fabric returnString.Append(" -cp "); // add libraries foreach(var library in version.Libraries) { bool rulesVaild = true; //check if native if (library.Natives is not null) continue; //rules check if (library.Rules is not null) { rulesVaild = false; foreach (var rule in library.Rules) { bool isRuleOsExist = rule.Os is not null; if (rule.Action == "allow" && rule.Os is null) { rulesVaild = true; continue; } if (rule.Os is not null) if (rule.Action == "allow" && (rule.Os.Name == "linux" && OperatingSystem.IsLinux() || rule.Os.Name == "windows" && OperatingSystem.IsWindows()) ) { rulesVaild = true; continue; } } } //if no path if (library.Downloads is null) //for optifine { string name = library.Name; var dirs = name.Split(':'); dirs[0] = dirs[0].Replace('.','/'); var libPath = String.Empty; foreach (var dir in dirs) { libPath += dir+"/"; } if (rulesVaild) returnString.Append(Settings.MinecraftForlderPath + "libraries/" + libPath + dirs[dirs.Length-2]+"-"+dirs[dirs.Length-1]+".jar;"); continue; } if (rulesVaild) returnString.Append(Settings.MinecraftForlderPath + "libraries/" + library.Downloads.Artifact.Path + separator); } Entity.Version.Version inheritsFrom = new(); if (version.InheritsFrom is null) returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.Id + "/" + version.Id + ".jar"); //main jar file else { //for forge, vanilla optifine, fabric //add libraries from inherited version var inheritsJsonString = File.ReadAllText(Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/" + version.InheritsFrom + ".json"); inheritsFrom = JsonSerializer.Deserialize(inheritsJsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true }); foreach (var library in inheritsFrom.Libraries) { bool rulesVaild = true; if (library.Natives is not null) continue; if (library.Rules is not null) { rulesVaild = false; foreach (var rule in library.Rules) { bool isRuleOsExist = rule.Os is not null; if (rule.Action == "allow" && rule.Os is null) { rulesVaild = true; continue; } if (rule.Os is not null) if (rule.Action == "allow" && (rule.Os.Name == "linux" && OperatingSystem.IsLinux() || rule.Os.Name == "windows" && OperatingSystem.IsWindows()) ) { rulesVaild = true; continue; } } } if(rulesVaild) returnString.Append(Settings.MinecraftForlderPath + "libraries/" + library.Downloads.Artifact.Path + separator); } //main jar file //check here if there is jar file not inherited //check if it is not 0kb size (fabric) var fileInfo = new FileInfo($"{Settings.MinecraftForlderPath}versions/{version.Id}/{version.Id}.jar"); if (fileInfo.Exists && fileInfo.Length > 0) returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.Id + "/" + version.Id + ".jar");//for optifine else returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/" + version.InheritsFrom + ".jar");//for forge } //check for jvm fabric options if (version.Arguments is not null && version.InheritsFrom is not null) { if (version.Arguments.Jvm is not null) foreach (var argument in version.Arguments.Jvm) { if (argument is null) continue; var type = argument.GetType(); if (!(argument is JsonElement)) continue; if (!(((JsonElement)argument).ValueKind == JsonValueKind.String)) continue; var value = ((JsonElement)argument).Deserialize(typeof(string)) as string; //for new forge versions (1.18, 1.19) if (value.Contains("${version_name}")) { value = value.Replace("${version_name}", version.InheritsFrom); } if (value.Contains("${library_directory}")) { value = value.Replace("${library_directory}", Settings.MinecraftForlderPath + "libraries/"); } if (value.Contains("${classpath_separator}")) { value = value.Replace("${classpath_separator}", ";"); } returnString.Append(" "); returnString.Append(value.Replace(" ", "")); } } //max ram if (Settings.setMaxRam) returnString.Append($" -Xmx{Settings.MaxRam}M "); returnString.Append(" " + version.MainClass); List args = new List(); List argsValues = new List(); if (version.Arguments is not null) { foreach (var argument in version.Arguments.Game) { if (argument is null) continue; var type = argument.GetType(); if (!(argument is JsonElement)) continue; if (!(((JsonElement)argument).ValueKind == JsonValueKind.String)) continue; var value = ((JsonElement)argument).Deserialize(typeof(string)); //if () if (!(value as string).Contains("--")) { argsValues.Add(value as string); continue; } args.Add(value as string); } } if (version.MinecraftArguments is not null) { var minecraftArguments = version.MinecraftArguments.Split(' '); //args = version.minecraftArguments.Split(' ').Where(x=> x.Contains("--")).ToList(); for (int i = 0; i < minecraftArguments.Count(); i++) { if (minecraftArguments[i].Contains("--")) args.Add(minecraftArguments[i]); else argsValues.Add(minecraftArguments[i]); } } Dictionary argsProvided = new Dictionary() { { "--username", false }, { "--version", false }, { "--gameDir", false}, { "--assetsDir", false }, { "--assetIndex", false }, { "--uuid", false }, { "--accessToken", false}, { "--userType", false}, { "--tweakClass", false } }; //check if all required arguments provided. Use inheritFrom if needed foreach (var arg in args) { argsProvided[arg] = true; } if (argsProvided.ContainsValue(false)) { if (inheritsFrom.Arguments is not null) { foreach (var argument in inheritsFrom.Arguments.Game) { if (argument is null) continue; var type = argument.GetType(); if (!(argument is JsonElement)) continue; if (!(((JsonElement)argument).ValueKind == JsonValueKind.String)) continue; var value = ((JsonElement)argument).Deserialize(typeof(string)); //if () if (!(value as string).Contains("--")) { argsValues.Add(value as string); continue; } if (!argsProvided.GetValueOrDefault(value as string, false)) { args.Add(value as string); argsProvided[value as string] = true; } } } if (inheritsFrom.MinecraftArguments is not null) { var minecraftArguments = inheritsFrom.MinecraftArguments.Split(' '); //args = version.minecraftArguments.Split(' ').Where(x=> x.Contains("--")).ToList(); for (int i = 0; i < minecraftArguments.Count(); i++) { if (minecraftArguments[i].Contains("--")) { args.Add(minecraftArguments[i]); argsProvided[minecraftArguments[i]] = true; } else argsValues.Add(minecraftArguments[i]); } } } for (int i = 0; i < args.Count; i++) { switch (args[i]) { case "--username": returnString.Append(" --username " + username); break; case "--version": returnString.Append(" --version " + version.Id /*"\"Copy of VeloeLauncher\""*/); break; case "--gameDir": //for forge if (!(argsValues.Where(x => x.Contains("forge")).Count() > 0 || version.Id.ToLower().Contains("fabric"))) returnString.Append(" --gameDir " + Settings.MinecraftForlderPath); else returnString.Append(" --gameDir " + Settings.MinecraftForlderPath + "versions/" + version.Id); break; case "--assetsDir": //for forge if (version.InheritsFrom is null) returnString.Append(" --assetsDir " + Settings.MinecraftForlderPath + "assets/" + version.Assets + "/"); else returnString.Append(" --assetsDir " + Settings.MinecraftForlderPath + "assets/" + inheritsFrom.Assets + "/"); break; case "--assetIndex": //for forge if (version.InheritsFrom is null) returnString.Append(" --assetIndex " + version.Assets); else returnString.Append(" --assetIndex " + inheritsFrom.Assets); break; case "--uuid": returnString.Append(" --uuid sample_token"); break; case "--accessToken": returnString.Append(" --accessToken sample_token"); break; case "--userType": returnString.Append(" --userType offline"); break; case "--userProperties": returnString.Append(" --userProperties " + "{\"veloelauncher\":[\"wtfisthis\"]}"); break; case "--versionType": returnString.Append(" --versionType " + version.Type); break; case "--tweakClass": returnString.Append(" --tweakClass"); if (argsValues[i] is not null) returnString.Append(" " + argsValues[i]); break; //for new forge default: if (argsValues[i] is not null && !argsValues[i].Contains("${")) { returnString.Append($" {args[i]} {argsValues[i]}"); } break; } } return returnString.ToString(); } }