diff --git a/GCMM/MainForm.cs b/GCMM/MainForm.cs index 77d5c31..26d73f9 100644 --- a/GCMM/MainForm.cs +++ b/GCMM/MainForm.cs @@ -22,8 +22,9 @@ namespace GCMM InitializeComponent(); } - private Dictionary mods = new Dictionary(); - private string defaultInfo = @" + private readonly Dictionary mods = new Dictionary(); + private readonly ModInfo gcipa = new ModInfo { Author = "modtainers", Name = "GCIPA" }; + private const string defaultInfo = @" Gamecraft Mod Manager If you click on a mod it will show some info about it. The install instructions there are usually for manual installs. @@ -234,12 +235,13 @@ You may also want to verify the game's files by right clicking the game in Steam } } - private void refreshbtn_Click(object sender, EventArgs e) + private async void refreshbtn_Click(object sender, EventArgs e) { - CheckIfPatched(); + CheckIfPatched(); //Set from placeholder var mods = GetInstalledMods(); - GetAvailableMods(); + await GetAvailableMods(); CheckUninstalledMods(mods); + CheckIfPatched(); //Check after getting the available mods to show GCIPA updates } private void validatebtn_Click(object sender, EventArgs e) diff --git a/GCMM/MainModInstaller.cs b/GCMM/MainModInstaller.cs index 949c074..cc1fa8c 100644 --- a/GCMM/MainModInstaller.cs +++ b/GCMM/MainModInstaller.cs @@ -29,7 +29,12 @@ namespace GCMM string disposition = client.ResponseHeaders["Content-Disposition"]; string filename = disposition.Substring(disposition.IndexOf("filename=") + 10).Replace("\"", ""); if (filename.EndsWith(".dll")) - File.Move(tmppath, plugins.FullName + Path.DirectorySeparatorChar + mod.Name + ".dll"); //Force mod name to make uninstalls & identifying easier + { + string name = plugins.FullName + Path.DirectorySeparatorChar + mod.Name + ".dll"; //Force mod name to make uninstalls & identifying easier + if (File.Exists(name)) + File.Delete(name); + File.Move(tmppath, name); + } else if (filename.EndsWith(".zip")) { bool pluginOnly = true; diff --git a/GCMM/MainModList.cs b/GCMM/MainModList.cs index 4cd7fca..77e0b3c 100644 --- a/GCMM/MainModList.cs +++ b/GCMM/MainModList.cs @@ -40,10 +40,23 @@ namespace GCMM { //Not a .NET assembly } } + try + { + string ipath = GamePath("\\IPA.exe"); //Heh + if (File.Exists(ipath)) + { + var an = AssemblyName.GetAssemblyName(ipath); + gcipa.Version = an.Version; + gcipa.LastUpdated = File.GetLastWriteTime(ipath); + } + } + catch (BadImageFormatException) + { //Not a .NET assembly + } return installed; } - public async void GetAvailableMods() + public async Task GetAvailableMods() { bool preview = GetExe()?.Contains("Preview") ?? false; using (var client = GetClient()) @@ -58,13 +71,14 @@ namespace GCMM Author = sp[0].Trim(), Name = sp[1].Trim() }; - if (await FetchModInfo(mod, preview)) //If it's actually a mod + if (await FetchModInfo(mod, preview, true)) //If it's actually a mod AddUpdateModInList(mod); } } + await FetchModInfo(gcipa, preview, false); } - public async Task FetchModInfo(ModInfo mod, bool preview) + public async Task FetchModInfo(ModInfo mod, bool preview, bool desc) { string repoURL = "/api/v1/repos/" + mod.Author + "/" + mod.Name + "/releases"; using (var client = GetClient()) @@ -108,13 +122,16 @@ namespace GCMM int getver(byte i) => ver.Length > i ? ver[i] : 0; //By default it sets values not present to -1, but we need them to be 0 mod.LatestVersion = new Version(getver(0), getver(1), getver(2), getver(3)); mod.UpdateDetails = release["name"] + "\n\n" + release["body"].ToString(); - try + if (desc) { - var obj = JObject.Parse(await client.DownloadStringTaskAsync("/api/v1/repos/" + mod.Author + "/" + mod.Name + "/contents/README.md")); - mod.Description = Encoding.UTF8.GetString(Convert.FromBase64String(obj["content"].ToString())); - } - catch(WebException) - { //It returns a HTTP 500 if it doesn't exist... + try + { + var obj = JObject.Parse(await client.DownloadStringTaskAsync("/api/v1/repos/" + mod.Author + "/" + mod.Name + "/contents/README.md")); + mod.Description = Encoding.UTF8.GetString(Convert.FromBase64String(obj["content"].ToString())); + } + catch (WebException) + { //It returns a HTTP 500 if it doesn't exist... + } } return true; } diff --git a/GCMM/MainPatcher.cs b/GCMM/MainPatcher.cs index 0928ab5..adeb8d7 100644 --- a/GCMM/MainPatcher.cs +++ b/GCMM/MainPatcher.cs @@ -10,6 +10,7 @@ using System.Net; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; +using System.Reflection; namespace GCMM { @@ -29,6 +30,12 @@ namespace GCMM playbtn.Text = pnp; return GameState.NoPatcher; } + if (gcipa.Updatable) + { + status.Text = "Status: Patcher outdated\nClicking play will update it"; + playbtn.Text = pnp; + return GameState.OldPatcher; + } string nopatch = "Status: Unpatched\nClicking Play patches it"; string gc = GetExe().Replace(".exe", ""); string backups = GamePath(@"\IPA\Backups\" + gc); @@ -71,31 +78,36 @@ namespace GCMM EndWork(false); return; case GameState.NoPatcher: + case GameState.OldPatcher: { - if (MessageBox.Show("The patcher (GCIPA) is not found. It's necessary to load the mods. It will be downloaded from https://git.exmods.org/modtainers/GCIPA/releases and ran to patch the game. You can unpatch to run without mods at any time.", "Patcher download needed", MessageBoxButtons.OKCancel) - == DialogResult.Cancel) + if (MessageBox.Show((status == GameState.NoPatcher + ? "The patcher (GCIPA) is not found. It's necessary to load the mods." + : "There is a patcher update available!" + ) + "\n\nIt will be downloaded from https://git.exmods.org/modtainers/GCIPA/releases and ran to patch the game. You can validate the game to restore the original game files or simply disable mods at any time.", + "Patcher download needed", MessageBoxButtons.OKCancel) == DialogResult.Cancel) { EndWork(); return; } string releases = "/api/v1/repos/modtainers/GCIPA/releases"; - string url; this.status.Text = "Status: Patching..."; using (WebClient client = GetClient()) { - url = JArray.Parse(await client.DownloadStringTaskAsync(releases)).First["assets"].First["browser_download_url"].ToString(); + string url = gcipa.DownloadURL; await client.DownloadFileTaskAsync(url, "IPA.zip"); using (var fs = new FileStream("IPA.zip", FileMode.Open)) using (var za = new ZipArchive(fs)) za.ExtractToDirectory(Settings.Default.GamePath, true); //Overwrite files that were left from a previous install of the patcher } } + GetInstalledMods(); //Update patcher state, should be fine for this rare event status = CheckIfPatched(); break; } switch (status) { case GameState.NoPatcher: //Make sure it actually worked + case GameState.OldPatcher: EndWork(false); return; case GameState.Unpatched: @@ -132,6 +144,7 @@ namespace GCMM { NotFound, NoPatcher, + OldPatcher, Unpatched, Patched }