Browse Source

Fix handling of game not found, refresh support

tags/v1.2.0
NorbiPeti 3 years ago
parent
commit
675daf1935
6 changed files with 144 additions and 68 deletions
  1. +19
    -2
      GCMM/MainForm.Designer.cs
  2. +14
    -4
      GCMM/MainForm.cs
  3. +3
    -4
      GCMM/MainModInstaller.cs
  4. +15
    -7
      GCMM/MainModList.cs
  5. +76
    -50
      GCMM/MainPatcher.cs
  6. +17
    -1
      GCMM/MainUtils.cs

+ 19
- 2
GCMM/MainForm.Designer.cs View File

@@ -49,6 +49,7 @@
this.findlog = new System.Windows.Forms.Button();
this.unpatched = new System.Windows.Forms.CheckBox();
this.modinfobox = new System.Windows.Forms.RichTextBox();
this.refreshbtn = new System.Windows.Forms.Button();
this.SuspendLayout();
//
// modlist
@@ -79,9 +80,9 @@
listViewItem1.Group = listViewGroup1;
this.modlist.Items.AddRange(new System.Windows.Forms.ListViewItem[] {
listViewItem1});
this.modlist.Location = new System.Drawing.Point(12, 12);
this.modlist.Location = new System.Drawing.Point(12, 47);
this.modlist.Name = "modlist";
this.modlist.Size = new System.Drawing.Size(491, 468);
this.modlist.Size = new System.Drawing.Size(491, 433);
this.modlist.TabIndex = 0;
this.modlist.UseCompatibleStateImageBehavior = false;
this.modlist.View = System.Windows.Forms.View.Details;
@@ -220,12 +221,27 @@
this.modinfobox.TabIndex = 9;
this.modinfobox.Text = "";
//
// refreshbtn
//
this.refreshbtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.Green;
this.refreshbtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(40)))), ((int)(((byte)(0)))));
this.refreshbtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.refreshbtn.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
this.refreshbtn.Location = new System.Drawing.Point(12, 12);
this.refreshbtn.Name = "refreshbtn";
this.refreshbtn.Size = new System.Drawing.Size(81, 29);
this.refreshbtn.TabIndex = 10;
this.refreshbtn.Text = "Refresh";
this.refreshbtn.UseVisualStyleBackColor = true;
this.refreshbtn.Click += new System.EventHandler(this.refreshbtn_Click);
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.BackColor = System.Drawing.Color.Black;
this.ClientSize = new System.Drawing.Size(784, 561);
this.Controls.Add(this.refreshbtn);
this.Controls.Add(this.modinfobox);
this.Controls.Add(this.unpatched);
this.Controls.Add(this.findlog);
@@ -260,6 +276,7 @@
private System.Windows.Forms.Button findlog;
private System.Windows.Forms.CheckBox unpatched;
private System.Windows.Forms.RichTextBox modinfobox;
private System.Windows.Forms.Button refreshbtn;
}
}


+ 14
- 4
GCMM/MainForm.cs View File

@@ -72,9 +72,7 @@ You may also want to verify the game's files by right clicking the game in Steam
DeleteEmptyPluginsDir(out bool pexists, out bool dexists);
if (!pexists && dexists)
unpatched.Checked = true; //It will call the event but that won't do anything
CheckIfPatched();
GetInstalledMods();
GetAvailableMods();
refreshbtn_Click(refreshbtn, null);
}

private async void playbtn_Click(object sender, EventArgs e)
@@ -183,12 +181,16 @@ You may also want to verify the game's files by right clicking the game in Steam
{
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
Process.Start("explorer.exe", $@"/select,{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}Low\Freejam\{GetExe().Replace(".exe", "")}\Player.log");
if (CheckNoExe(out string exe))
return;
Process.Start("explorer.exe", $@"/select,{Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)}Low\Freejam\{exe.Replace(".exe", "")}\Player.log");
}
}

private void unpatched_CheckedChanged(object sender, EventArgs e)
{ //Not using the patcher's revert option because sometimes it restores the wrong files - the game can be patched without mods
if (CheckNoExe())
return;
CheckIfPatched();
modlist_SelectedIndexChanged(modlist, null);
string plugins = GamePath("\\Plugins");
@@ -231,5 +233,13 @@ You may also want to verify the game's files by right clicking the game in Steam
dexists = false;
}
}

private void refreshbtn_Click(object sender, EventArgs e)
{
CheckIfPatched();
var mods = GetInstalledMods();
GetAvailableMods();
CheckUninstalledMods(mods);
}
}
}

+ 3
- 4
GCMM/MainModInstaller.cs View File

@@ -16,11 +16,8 @@ namespace GCMM
public async Task InstallMod(ModInfo mod)
{
if (mod.DownloadURL == null) return;
if (GetExe() == null)
{
MessageBox.Show("Gamecraft not found. Set the correct path in Settings.");
if (CheckNoExe())
return;
}
if (mod.Name != "GamecraftModdingAPI")
await UpdateAPI();
var tmp = Directory.CreateDirectory("temp");
@@ -140,6 +137,8 @@ namespace GCMM

public async Task UpdateAPI()
{
if (!mods.ContainsKey("GamecraftModdingAPI"))
return;
var gcmapi = mods["GamecraftModdingAPI"];
if (!gcmapi.Installed || gcmapi.Updatable)
{


+ 15
- 7
GCMM/MainModList.cs View File

@@ -17,13 +17,14 @@ namespace GCMM
partial class MainForm
{

public void GetInstalledMods()
public HashSet<string> GetInstalledMods()
{
bool disabled = false;
if (!Directory.Exists(GamePath("\\Plugins")))
if (Directory.Exists(GamePath("\\Plugins_Disabled")))
disabled = true;
else return;
else return new HashSet<string>();
var installed = new HashSet<string>();
foreach (var modPath in Directory.GetFiles(GamePath(disabled ? @"\Plugins_Disabled" : @"\Plugins"), "*.dll"))
{
try
@@ -31,12 +32,15 @@ namespace GCMM
var an = AssemblyName.GetAssemblyName(modPath);
if (an.Name == "0Harmony") continue;
//Use filename to avoid differences between repository & assembly name casing
AddUpdateModInList(new ModInfo { Name = Path.GetFileNameWithoutExtension(modPath), Version = an.Version, LastUpdated = File.GetLastWriteTime(modPath) });
var mod = new ModInfo { Name = Path.GetFileNameWithoutExtension(modPath), Version = an.Version, LastUpdated = File.GetLastWriteTime(modPath) };
AddUpdateModInList(mod);
installed.Add(mod.Name);
}
catch (BadImageFormatException)
{ //Not a .NET assembly
}
}
return installed;
}

public async void GetAvailableMods()
@@ -127,7 +131,7 @@ namespace GCMM
item = modlist.Items[mod.Name];
var items = item.SubItems;
omod.Author = mod.Author ?? omod.Author;
omod.Version = mod.Version ?? omod.Version;
omod.Version = mod.Version ?? omod.Version; //If the object comes from the dictionary then it's directly modified (uninstall)
omod.LatestVersion = mod.LatestVersion ?? omod.LatestVersion;
omod.LastUpdated = mod.LastUpdated == default ? omod.LastUpdated : mod.LastUpdated;
omod.Description = mod.Description ?? omod.Description;
@@ -152,10 +156,14 @@ namespace GCMM
item.ForeColor = modlist.ForeColor;
}

public void RemoveModFromList(ModInfo mod)
public void CheckUninstalledMods(HashSet<string> installed)
{
if (mods.Remove(mod.Name))
modlist.Items.RemoveByKey(mod.Name);
foreach (string name in mods.Keys.Except(installed))
{
var mod = mods[name];
mod.Version = null;
AddUpdateModInList(mod);
}
}
}
}

+ 76
- 50
GCMM/MainPatcher.cs View File

@@ -15,14 +15,19 @@ namespace GCMM
{
partial class MainForm
{
public bool? CheckIfPatched()
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 null;
return GameState.NoPatcher;
}
string nopatch = "Status: Unpatched\nClicking Play patches it";
string gc = GetExe().Replace(".exe", "");
@@ -31,14 +36,14 @@ namespace GCMM
{
status.Text = nopatch;
playbtn.Text = pnp;
return false;
return GameState.Unpatched;
}
string backup = Directory.EnumerateDirectories(backups).OrderByDescending(s => s).FirstOrDefault();
if (backup == null)
{
status.Text = nopatch;
playbtn.Text = pnp;
return false;
return GameState.Unpatched;
}
if (File.GetLastWriteTime(GamePath($@"\{gc}_Data\Managed\Assembly-CSharp.dll"))
> //If the file was updated at least 2 minutes after patching
@@ -46,11 +51,11 @@ namespace GCMM
{
status.Text = nopatch;
playbtn.Text = pnp;
return false;
return GameState.Unpatched;
}
status.Text = "Status: " + (unpatched.Checked ? "Mods disabled" : "Patched");
playbtn.Text = "Play" + (unpatched.Checked ? " unmodded" : "");
return true;
return GameState.Patched;
}

public async Task PatchStartGame()
@@ -58,55 +63,76 @@ namespace GCMM
if (!BeginWork()) return;
foreach (ListViewItem item in modlist.SelectedItems)
item.Selected = false;
if (!CheckIfPatched().HasValue)
var status = CheckIfPatched();
switch (status)
{
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)
{
EndWork();
case GameState.NotFound:
MessageBox.Show("Gamecraft not found! Set the correct path in Settings.");
EndWork(false);
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();
await client.DownloadFileTaskAsync(url, "IPA.zip");
ZipFile.ExtractToDirectory("IPA.zip", Settings.Default.GamePath);
}
case GameState.NoPatcher:
{
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)
{
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();
await client.DownloadFileTaskAsync(url, "IPA.zip");
ZipFile.ExtractToDirectory("IPA.zip", Settings.Default.GamePath);
}
}
break;
}
bool? status = CheckIfPatched();
if (!status.HasValue) //Make sure it actually worked
if (status != GameState.NotFound && status != GameState.NoPatcher)
status = CheckIfPatched();
switch (status)
{
EndWork(false);
return;
}
if (!status.Value)
{ //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;
case GameState.NoPatcher: //Make sure it actually worked
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;
}
else
CheckStartGame(null, null);
}

public enum GameState
{
NotFound,
NoPatcher,
Unpatched,
Patched
}
}
}

+ 17
- 1
GCMM/MainUtils.cs View File

@@ -76,7 +76,7 @@ namespace GCMM
status.Text = "Status: Patching failed";
return;
}
if ((CheckIfPatched() ?? false) || unpatched.Checked)
if (CheckIfPatched() == GameState.Patched || unpatched.Checked)
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
Process.Start("steam://run/1078000/");
else
@@ -144,5 +144,21 @@ namespace GCMM
return "GamecraftPreview.exe";
return null;
}

private bool CheckNoExe()
{
return CheckNoExe(out _);
}

private bool CheckNoExe(out string path)
{
path = GetExe();
if (path == null)
{
MessageBox.Show("Gamecraft not found! Set the correct path in Settings.");
return true;
}
return false;
}
}
}

Loading…
Cancel
Save