StartCommandBuilder.cs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Text.Json;
  7. using System.Threading.Tasks;
  8. namespace VeloeMinecraftLauncher.MinecraftLauncher;
  9. internal static class StartCommandBuilder
  10. {
  11. public static string Build(Entity.Version.Version version, string username)
  12. {
  13. var returnString = new StringBuilder();
  14. char separator = ':';
  15. if (OperatingSystem.IsWindows())
  16. separator = ';';
  17. if (version is null)
  18. return returnString.ToString();
  19. // setting natives folder
  20. if (version.InheritsFrom is null)
  21. returnString.Append($"-Djava.library.path={Settings.MinecraftForlderPath + "versions/" + version.Id + "/natives/"}");
  22. else
  23. returnString.Append($"-Djava.library.path={Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/natives/"}"); //for forge, vanilla optifine, fabric
  24. returnString.Append(" -cp ");
  25. // add libraries
  26. foreach(var library in version.Libraries)
  27. {
  28. bool rulesVaild = true;
  29. //check if native
  30. if (library.Natives is not null)
  31. continue;
  32. //rules check
  33. if (library.Rules is not null)
  34. {
  35. rulesVaild = false;
  36. foreach (var rule in library.Rules)
  37. {
  38. bool isRuleOsExist = rule.Os is not null;
  39. if (rule.Action == "allow" && rule.Os is null)
  40. {
  41. rulesVaild = true;
  42. continue;
  43. }
  44. if (rule.Os is not null)
  45. if (rule.Action == "allow" &&
  46. (rule.Os.Name == "linux" && OperatingSystem.IsLinux() ||
  47. rule.Os.Name == "windows" && OperatingSystem.IsWindows())
  48. )
  49. {
  50. rulesVaild = true;
  51. continue;
  52. }
  53. }
  54. }
  55. //if no path
  56. if (library.Downloads is null) //for optifine
  57. {
  58. string name = library.Name;
  59. var dirs = name.Split(':');
  60. dirs[0] = dirs[0].Replace('.','/');
  61. var libPath = String.Empty;
  62. foreach (var dir in dirs)
  63. {
  64. libPath += dir+"/";
  65. }
  66. if (rulesVaild)
  67. returnString.Append(Settings.MinecraftForlderPath + "libraries/" + libPath + dirs[dirs.Length-2]+"-"+dirs[dirs.Length-1]+".jar;");
  68. continue;
  69. }
  70. if (rulesVaild)
  71. returnString.Append(Settings.MinecraftForlderPath + "libraries/" + library.Downloads.Artifact.Path + separator);
  72. }
  73. Entity.Version.Version inheritsFrom = new();
  74. if (version.InheritsFrom is null)
  75. returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.Id + "/" + version.Id + ".jar"); //main jar file
  76. else
  77. {
  78. //for forge, vanilla optifine, fabric
  79. //add libraries from inherited version
  80. var inheritsJsonString = File.ReadAllText(Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/" + version.InheritsFrom + ".json");
  81. inheritsFrom = JsonSerializer.Deserialize<Entity.Version.Version>(inheritsJsonString, new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
  82. foreach (var library in inheritsFrom.Libraries)
  83. {
  84. bool rulesVaild = true;
  85. if (library.Natives is not null)
  86. continue;
  87. if (library.Rules is not null)
  88. {
  89. rulesVaild = false;
  90. foreach (var rule in library.Rules)
  91. {
  92. bool isRuleOsExist = rule.Os is not null;
  93. if (rule.Action == "allow" && rule.Os is null)
  94. {
  95. rulesVaild = true;
  96. continue;
  97. }
  98. if (rule.Os is not null)
  99. if (rule.Action == "allow" &&
  100. (rule.Os.Name == "linux" && OperatingSystem.IsLinux() ||
  101. rule.Os.Name == "windows" && OperatingSystem.IsWindows())
  102. )
  103. {
  104. rulesVaild = true;
  105. continue;
  106. }
  107. }
  108. }
  109. if(rulesVaild)
  110. returnString.Append(Settings.MinecraftForlderPath + "libraries/" + library.Downloads.Artifact.Path + separator);
  111. }
  112. //main jar file
  113. //check here if there is jar file not inherited
  114. //check if it is not 0kb size (fabric)
  115. var fileInfo = new FileInfo($"{Settings.MinecraftForlderPath}versions/{version.Id}/{version.Id}.jar");
  116. if (fileInfo.Exists && fileInfo.Length > 0)
  117. returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.Id + "/" + version.Id + ".jar");//for optifine
  118. else
  119. returnString.Append(Settings.MinecraftForlderPath + "versions/" + version.InheritsFrom + "/" + version.InheritsFrom + ".jar");//for forge
  120. }
  121. //check for jvm fabric options
  122. if (version.Arguments is not null && version.InheritsFrom is not null)
  123. {
  124. if (version.Arguments.Jvm is not null)
  125. foreach (var argument in version.Arguments.Jvm)
  126. {
  127. if (argument is null)
  128. continue;
  129. var type = argument.GetType();
  130. if (!(argument is JsonElement))
  131. continue;
  132. if (!(((JsonElement)argument).ValueKind == JsonValueKind.String))
  133. continue;
  134. var value = ((JsonElement)argument).Deserialize(typeof(string)) as string;
  135. //for new forge versions (1.18, 1.19)
  136. if (value.Contains("${version_name}"))
  137. {
  138. value = value.Replace("${version_name}", version.InheritsFrom);
  139. }
  140. if (value.Contains("${library_directory}"))
  141. {
  142. value = value.Replace("${library_directory}", Settings.MinecraftForlderPath + "libraries/");
  143. }
  144. if (value.Contains("${classpath_separator}"))
  145. {
  146. value = value.Replace("${classpath_separator}", ";");
  147. }
  148. returnString.Append(" ");
  149. returnString.Append(value.Replace(" ", ""));
  150. }
  151. }
  152. //max ram
  153. if (Settings.setMaxRam)
  154. returnString.Append($" -Xmx{Settings.MaxRam}M ");
  155. returnString.Append(" " + version.MainClass);
  156. List<string> args = new List<string>();
  157. List<string> argsValues = new List<string>();
  158. if (version.Arguments is not null)
  159. {
  160. foreach (var argument in version.Arguments.Game)
  161. {
  162. if (argument is null)
  163. continue;
  164. var type = argument.GetType();
  165. if (!(argument is JsonElement))
  166. continue;
  167. if (!(((JsonElement)argument).ValueKind == JsonValueKind.String))
  168. continue;
  169. var value = ((JsonElement)argument).Deserialize(typeof(string));
  170. //if ()
  171. if (!(value as string).Contains("--"))
  172. {
  173. argsValues.Add(value as string);
  174. continue;
  175. }
  176. args.Add(value as string);
  177. }
  178. }
  179. if (version.MinecraftArguments is not null)
  180. {
  181. var minecraftArguments = version.MinecraftArguments.Split(' ');
  182. //args = version.minecraftArguments.Split(' ').Where(x=> x.Contains("--")).ToList();
  183. for (int i = 0; i < minecraftArguments.Count(); i++)
  184. {
  185. if (minecraftArguments[i].Contains("--"))
  186. args.Add(minecraftArguments[i]);
  187. else
  188. argsValues.Add(minecraftArguments[i]);
  189. }
  190. }
  191. Dictionary<string, bool> argsProvided = new Dictionary<string, bool>()
  192. {
  193. { "--username", false },
  194. { "--version", false },
  195. { "--gameDir", false},
  196. { "--assetsDir", false },
  197. { "--assetIndex", false },
  198. { "--uuid", false },
  199. { "--accessToken", false},
  200. { "--userType", false},
  201. { "--tweakClass", false }
  202. };
  203. //check if all required arguments provided. Use inheritFrom if needed
  204. foreach (var arg in args)
  205. {
  206. argsProvided[arg] = true;
  207. }
  208. if (argsProvided.ContainsValue(false))
  209. {
  210. if (inheritsFrom.Arguments is not null)
  211. {
  212. foreach (var argument in inheritsFrom.Arguments.Game)
  213. {
  214. if (argument is null)
  215. continue;
  216. var type = argument.GetType();
  217. if (!(argument is JsonElement))
  218. continue;
  219. if (!(((JsonElement)argument).ValueKind == JsonValueKind.String))
  220. continue;
  221. var value = ((JsonElement)argument).Deserialize(typeof(string));
  222. //if ()
  223. if (!(value as string).Contains("--"))
  224. {
  225. argsValues.Add(value as string);
  226. continue;
  227. }
  228. if (!argsProvided.GetValueOrDefault(value as string, false))
  229. {
  230. args.Add(value as string);
  231. argsProvided[value as string] = true;
  232. }
  233. }
  234. }
  235. if (inheritsFrom.MinecraftArguments is not null)
  236. {
  237. var minecraftArguments = inheritsFrom.MinecraftArguments.Split(' ');
  238. //args = version.minecraftArguments.Split(' ').Where(x=> x.Contains("--")).ToList();
  239. for (int i = 0; i < minecraftArguments.Count(); i++)
  240. {
  241. if (minecraftArguments[i].Contains("--"))
  242. {
  243. args.Add(minecraftArguments[i]);
  244. argsProvided[minecraftArguments[i]] = true;
  245. }
  246. else
  247. argsValues.Add(minecraftArguments[i]);
  248. }
  249. }
  250. }
  251. for (int i = 0; i < args.Count; i++)
  252. {
  253. switch (args[i])
  254. {
  255. case "--username":
  256. returnString.Append(" --username " + username);
  257. break;
  258. case "--version":
  259. returnString.Append(" --version " + version.Id /*"\"Copy of VeloeLauncher\""*/);
  260. break;
  261. case "--gameDir":
  262. //for forge
  263. if (!(argsValues.Where(x => x.Contains("forge")).Count() > 0 || version.Id.ToLower().Contains("fabric")))
  264. returnString.Append(" --gameDir " + Settings.MinecraftForlderPath);
  265. else
  266. returnString.Append(" --gameDir " + Settings.MinecraftForlderPath + "versions/" + version.Id);
  267. break;
  268. case "--assetsDir":
  269. //for forge
  270. if (version.InheritsFrom is null)
  271. returnString.Append(" --assetsDir " + Settings.MinecraftForlderPath + "assets/" + version.Assets + "/");
  272. else
  273. returnString.Append(" --assetsDir " + Settings.MinecraftForlderPath + "assets/" + inheritsFrom.Assets + "/");
  274. break;
  275. case "--assetIndex":
  276. //for forge
  277. if (version.InheritsFrom is null)
  278. returnString.Append(" --assetIndex " + version.Assets);
  279. else
  280. returnString.Append(" --assetIndex " + inheritsFrom.Assets);
  281. break;
  282. case "--uuid":
  283. returnString.Append(" --uuid sample_token");
  284. break;
  285. case "--accessToken":
  286. returnString.Append(" --accessToken sample_token");
  287. break;
  288. case "--userType":
  289. returnString.Append(" --userType offline");
  290. break;
  291. case "--userProperties":
  292. returnString.Append(" --userProperties " + "{\"veloelauncher\":[\"wtfisthis\"]}");
  293. break;
  294. case "--versionType":
  295. returnString.Append(" --versionType " + version.Type);
  296. break;
  297. case "--tweakClass":
  298. returnString.Append(" --tweakClass");
  299. if (argsValues[i] is not null)
  300. returnString.Append(" " + argsValues[i]);
  301. break;
  302. //for new forge
  303. default:
  304. if (argsValues[i] is not null && !argsValues[i].Contains("${"))
  305. {
  306. returnString.Append($" {args[i]} {argsValues[i]}");
  307. }
  308. break;
  309. }
  310. }
  311. return returnString.ToString();
  312. }
  313. }