Techblox Mod Manager / Launcher
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

239 řádky
9.1KB

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