NorbiPeti
f522432208
If the mod consists of a dll then it failed to update it because it already existed Added support for updating GCIPA, using both the existing mod info fetching and the patcher downloading code
152 lines
6.3 KiB
C#
152 lines
6.3 KiB
C#
using GCMM.Properties;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO.Compression;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Net;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows.Forms;
|
|
using System.Reflection;
|
|
|
|
namespace GCMM
|
|
{
|
|
partial class MainForm
|
|
{
|
|
public GameState CheckIfPatched()
|
|
{
|
|
if (GetExe() == null)
|
|
{
|
|
status.Text = "Status: Game not found";
|
|
return GameState.NotFound;
|
|
}
|
|
string pnp = "Patch && Play";
|
|
if (!File.Exists(GamePath(@"\IPA.exe")))
|
|
{
|
|
status.Text = "Status: Patcher missing\nClicking Play will install it";
|
|
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);
|
|
if (!Directory.Exists(backups))
|
|
{
|
|
status.Text = nopatch;
|
|
playbtn.Text = pnp;
|
|
return GameState.Unpatched;
|
|
}
|
|
string backup = Directory.EnumerateDirectories(backups).OrderByDescending(name => Directory.GetLastWriteTimeUtc(name)).FirstOrDefault();
|
|
if (backup == null)
|
|
{
|
|
status.Text = nopatch;
|
|
playbtn.Text = pnp;
|
|
return GameState.Unpatched;
|
|
}
|
|
if (File.GetLastWriteTime(GamePath($@"\{gc}_Data\Managed\Assembly-CSharp.dll"))
|
|
> //If the file was updated at least 2 minutes after patching
|
|
Directory.GetLastWriteTime(backup).AddMinutes(2))
|
|
{
|
|
status.Text = nopatch;
|
|
playbtn.Text = pnp;
|
|
return GameState.Unpatched;
|
|
}
|
|
status.Text = "Status: " + (unpatched.Checked ? "Mods disabled" : "Patched");
|
|
playbtn.Text = "Play" + (unpatched.Checked ? " unmodded" : "");
|
|
return GameState.Patched;
|
|
}
|
|
|
|
public async Task PatchStartGame()
|
|
{
|
|
if (!BeginWork()) return;
|
|
foreach (ListViewItem item in modlist.SelectedItems)
|
|
item.Selected = false;
|
|
var status = CheckIfPatched();
|
|
switch (status)
|
|
{
|
|
case GameState.NotFound:
|
|
MessageBox.Show("Gamecraft not found! Set the correct path in Settings.");
|
|
EndWork(false);
|
|
return;
|
|
case GameState.NoPatcher:
|
|
case GameState.OldPatcher:
|
|
{
|
|
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";
|
|
this.status.Text = "Status: Patching...";
|
|
using (WebClient client = GetClient())
|
|
{
|
|
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:
|
|
{ //TODO: Wine
|
|
var psi = new ProcessStartInfo(GamePath(@"\IPA.exe"), GetExe() + " --nowait")
|
|
{
|
|
UseShellExecute = false,
|
|
RedirectStandardError = true,
|
|
RedirectStandardOutput = true,
|
|
WorkingDirectory = Settings.Default.GamePath,
|
|
CreateNoWindow = true
|
|
};
|
|
var process = Process.Start(psi);
|
|
process.BeginErrorReadLine();
|
|
process.BeginOutputReadLine();
|
|
process.EnableRaisingEvents = true;
|
|
modinfobox.Text = "";
|
|
DataReceivedEventHandler onoutput = (sender, e) =>
|
|
{
|
|
Invoke((Action)(() => modinfobox.Text += e.Data + Environment.NewLine));
|
|
};
|
|
process.OutputDataReceived += onoutput;
|
|
process.ErrorDataReceived += onoutput;
|
|
process.Exited += CheckStartGame;
|
|
}
|
|
break;
|
|
case GameState.Patched:
|
|
CheckStartGame(null, null);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public enum GameState
|
|
{
|
|
NotFound,
|
|
NoPatcher,
|
|
OldPatcher,
|
|
Unpatched,
|
|
Patched
|
|
}
|
|
}
|
|
}
|