Techblox Mod Manager / Launcher
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

243 linhas
9.8KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Diagnostics;
  4. using System.Drawing;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Net;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10. namespace GCMM
  11. {
  12. partial class MainForm
  13. {
  14. public void UpdateButton(Button button, bool enabled)
  15. {
  16. if (enabled)
  17. {
  18. button.ForeColor = Color.Lime;
  19. button.FlatAppearance.MouseOverBackColor = Color.FromArgb(0, 40, 0);
  20. button.FlatAppearance.MouseDownBackColor = Color.Green;
  21. }
  22. else
  23. {
  24. button.ForeColor = Color.Green;
  25. button.FlatAppearance.MouseOverBackColor = Color.Black;
  26. button.FlatAppearance.MouseDownBackColor = Color.Black;
  27. }
  28. }
  29. private bool EnableDisableAutoPatching(bool enable)
  30. {
  31. foreach (string file in Directory.EnumerateFiles(GamePath("")))
  32. File.Copy(file, Path.GetFileName(file), true);
  33. var toSymLink = new List<string> {GamePath("\\MonoBleedingEdge")};
  34. Directory.CreateDirectory("TechbloxPreview_Data");
  35. toSymLink.AddRange(Directory.EnumerateDirectories(GamePath("\\TechbloxPreview_Data"))
  36. .Except(new[] {"Managed"}));
  37. foreach (string file in Directory.EnumerateFiles(GamePath("\\TechbloxPreview_Data")))
  38. File.Copy(file, "TechbloxPreview_Data\\" + Path.GetFileName(file), true);
  39. Directory.CreateDirectory("TechbloxPreview_Data\\Managed");
  40. foreach (string file in Directory.EnumerateFiles(GamePath("\\TechbloxPreview_Data\\Managed")))
  41. File.Copy(file, "TechbloxPreview_Data\\Managed\\" + Path.GetFileName(file), true);
  42. return toSymLink.Select(targetName => (sourceName: targetName.Replace(GamePath("\\"), ""), targetName))
  43. .Where(tuple => !Directory.Exists(tuple.sourceName))
  44. .All(tuple => SymLinks.CreateFolderSymbolicLink(tuple.sourceName, tuple.targetName));
  45. }
  46. public void EnableDisableAutoPatchingWithDialog(bool enable)
  47. {
  48. try
  49. {
  50. if (EnableDisableAutoPatching(enable))
  51. {
  52. DialogUtils.ShowInfo(resources.GetString("Change_launch_settings_done"),
  53. resources.GetString("Change_launch_settings_title"));
  54. Configuration.AutoPatch = enable ? AutoPatchingState.Enabled : AutoPatchingState.Disabled;
  55. }
  56. else
  57. DialogUtils.ShowError(resources.GetString("Change_launch_settings_error"),
  58. resources.GetString("Change_launch_settings_title"));
  59. }
  60. catch (Exception e)
  61. {
  62. DialogUtils.ShowError(resources.GetString("Change_launch_settings_error") + "\n\n" + e,
  63. resources.GetString("Change_launch_settings_title"));
  64. }
  65. }
  66. public string GetGameFolder()
  67. {
  68. string launcherConfig =
  69. Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
  70. "Techblox Launcher", "launcher_settings.ini");
  71. if (!File.Exists(launcherConfig)) return null;
  72. string path = File.ReadLines(launcherConfig)
  73. .FirstOrDefault(line => line.StartsWith("133062..GAME_PATH="))
  74. ?.Substring("133062..GAME_PATH=".Length).Replace("/TBMM/", "/");
  75. if (path != null) path = (path + "StandaloneWindows64").Replace('/', Path.DirectorySeparatorChar);
  76. if (path != null && GetExe(path) != null) return path;
  77. return null;
  78. }
  79. public string SelectGameFolder()
  80. {
  81. var ofd = new OpenFileDialog();
  82. ofd.Filter = "Techblox executable|Techblox.exe|Techblox Preview executable|TechbloxPreview.exe";
  83. ofd.Title = "Game location";
  84. ofd.CheckFileExists = true;
  85. ofd.ShowDialog();
  86. return string.IsNullOrWhiteSpace(ofd.FileName) ? null : Directory.GetParent(ofd.FileName)?.FullName;
  87. }
  88. private (EventHandler, Task) CheckStartGame(string command)
  89. {
  90. var tcs = new TaskCompletionSource<object>();
  91. return ((sender, e) =>
  92. {
  93. Action act = async () =>
  94. {
  95. if (((sender as Process)?.ExitCode ?? 0) != 0)
  96. {
  97. status.Text = "Status: Patching failed";
  98. return;
  99. }
  100. if (CheckIfPatched() == GameState.Patched || unpatched.Checked)
  101. if (command != null)
  102. {
  103. if (sender is Process) //Patched just now
  104. CheckCompatibilityAndDisableMods();
  105. await CheckModUpdatesAsync();
  106. Process.Start(command);
  107. }
  108. if (Environment.OSVersion.Platform == PlatformID.Win32NT)
  109. Process.Start(new ProcessStartInfo(GamePath("\\" + GetExe()))
  110. {
  111. WorkingDirectory = GamePath("\\") //Mods are only loaded if the working directory is correct
  112. });
  113. EndWork(false);
  114. tcs.SetResult(null);
  115. };
  116. if (InvokeRequired)
  117. Invoke(act);
  118. else
  119. act();
  120. }, tcs.Task);
  121. }
  122. private void CheckCompatibilityAndDisableMods()
  123. {
  124. if (!unpatched.Checked && MessageBox.Show("If the game updated just now, some mods may be incompatible or they may work just fine." +
  125. " Do you want to try running with mods?" +
  126. "\n\nClick Yes to start the game with mods (after a small update or if you just installed GCMM)" +
  127. "\nClick No to disable mods before starting the game (after a major update)" +
  128. "\n\nYou can always enable/disable mods by launching GCMM.",
  129. "Possible incompatibility warning", MessageBoxButtons.YesNo) == DialogResult.No)
  130. unpatched.Checked = true;
  131. }
  132. private async Task CheckModUpdatesAsync()
  133. {
  134. var updatable = mods.Values.Where(mod => mod.Updatable).ToArray();
  135. if (updatable.Length == 0)
  136. return;
  137. if (MessageBox.Show("Mod update(s) available!\n\n"
  138. + updatable.Select(mod => mod.Name + " " + mod.LatestVersion).Aggregate((a, b) => a + "\n")
  139. + "\n\nDo you want to update them now? You can also update later by opening GCMM.",
  140. "Update(s) available", MessageBoxButtons.YesNo) == DialogResult.No)
  141. return;
  142. foreach (var mod in updatable)
  143. await InstallMod(mod);
  144. MessageBox.Show("Mods updated");
  145. }
  146. public WebClient GetClient()
  147. {
  148. var client = new WebClient();
  149. client.Headers.Clear();
  150. client.Headers[HttpRequestHeader.Accept] = "application/json";
  151. client.BaseAddress = "https://git.exmods.org";
  152. return client;
  153. }
  154. private bool working = false;
  155. /// <summary>
  156. /// Some simple "locking", only allow one operation at a time
  157. /// </summary>
  158. /// <returns>Whether the work can begin</returns>
  159. public bool BeginWork()
  160. {
  161. if (working) return false;
  162. working = true;
  163. UpdateButton(playbtn, false);
  164. UpdateButton(installbtn, false);
  165. UpdateButton(uninstallbtn, false);
  166. UpdateButton(settingsbtn, false);
  167. unpatched.Enabled = false;
  168. return true;
  169. }
  170. public void EndWork(bool desc = true)
  171. {
  172. working = false;
  173. UpdateButton(playbtn, true);
  174. UpdateButton(settingsbtn, true);
  175. if (desc)
  176. modlist_SelectedIndexChanged(modlist, null);
  177. unpatched.Enabled = true;
  178. }
  179. /// <summary>
  180. /// Path must start with \
  181. /// </summary>
  182. /// <param name="path"></param>
  183. /// <param name="gamepath"></param>
  184. /// <returns></returns>
  185. public string GamePath(string path, string gamepath = null)
  186. {
  187. return ((gamepath ?? Configuration.GamePath) + path).Replace('\\', Path.DirectorySeparatorChar);
  188. }
  189. public string GetExe(string path = null)
  190. {
  191. if (File.Exists(GamePath("\\Techblox.exe", path)))
  192. return "Techblox.exe";
  193. if (File.Exists(GamePath("\\TechbloxPreview.exe", path)))
  194. return "TechbloxPreview.exe";
  195. return null;
  196. }
  197. private bool CheckNoExe()
  198. {
  199. return CheckNoExe(out _);
  200. }
  201. private bool CheckNoExe(out string path)
  202. {
  203. path = GetExe();
  204. if (path == null)
  205. {
  206. MessageBox.Show("Techblox not found! Set the correct path in Settings.");
  207. return true;
  208. }
  209. return false;
  210. }
  211. public async Task<DateTime> GetLastGameUpdateTime()
  212. {
  213. /*using (var client = GetClient())
  214. {
  215. string html = await client.DownloadStringTaskAsync("https://api.steamcmd.net/v1/info/1078000");
  216. var regex = new Regex("<i>timeupdated:</i>[^<]*<b>([^<]*)</b>");
  217. var match = regex.Match(html);
  218. if (!match.Success)
  219. return default;
  220. return new DateTime(1970, 1, 1).AddSeconds(long.Parse(match.Groups[1].Value));
  221. }*/
  222. //return new DateTime(2020, 12, 28);
  223. return default;
  224. }
  225. }
  226. }