Techblox Mod Manager / Launcher
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

MainUtils.cs 9.0KB

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