Browse Source

Installing works, buttons are disabled while working

tags/v1.0.0
NorbiPeti 3 years ago
parent
commit
b03b63294e
10 changed files with 226 additions and 24 deletions
  1. +4
    -0
      GCMM/GCMM.csproj
  2. +7
    -6
      GCMM/MainForm.Designer.cs
  3. +46
    -0
      GCMM/MainForm.cs
  4. +58
    -0
      GCMM/MainModInstaller.cs
  5. +34
    -11
      GCMM/MainModList.cs
  6. +0
    -5
      GCMM/MainPatcher.cs
  7. +24
    -0
      GCMM/MainUtils.cs
  8. +2
    -2
      GCMM/ModInfo.cs
  9. +42
    -0
      GCMM/ZipArchiveExtensions.cs
  10. +9
    -0
      GCMM/modlist.txt

+ 4
- 0
GCMM/GCMM.csproj View File

@@ -17,6 +17,7 @@

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="System.IO.Compression" Version="4.3.0" />
</ItemGroup>

<ItemGroup>
@@ -35,6 +36,9 @@
</ItemGroup>

<ItemGroup>
<None Update="modlist.txt">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>


+ 7
- 6
GCMM/MainForm.Designer.cs View File

@@ -38,6 +38,7 @@
System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(MainForm));
this.modlist = new System.Windows.Forms.ListView();
this.modName = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.modAuthor = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.modVersion = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.modTimestamp = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.status = new System.Windows.Forms.Label();
@@ -46,7 +47,6 @@
this.modinfobox = new System.Windows.Forms.TextBox();
this.playbtn = new System.Windows.Forms.Button();
this.settingsbtn = new System.Windows.Forms.Button();
this.modAuthor = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader()));
this.SuspendLayout();
//
// modlist
@@ -90,6 +90,11 @@
this.modName.Text = "Name";
this.modName.Width = 148;
//
// modAuthor
//
this.modAuthor.Text = "Author";
this.modAuthor.Width = 142;
//
// modVersion
//
this.modVersion.Text = "Version";
@@ -126,6 +131,7 @@
this.installbtn.TabIndex = 2;
this.installbtn.Text = "Install mod";
this.installbtn.UseVisualStyleBackColor = true;
this.installbtn.Click += new System.EventHandler(this.installbtn_Click);
//
// uninstallbtn
//
@@ -186,11 +192,6 @@
this.settingsbtn.UseVisualStyleBackColor = true;
this.settingsbtn.Click += new System.EventHandler(this.settingsbtn_Click);
//
// modAuthor
//
this.modAuthor.Text = "Author";
this.modAuthor.Width = 142;
//
// MainForm
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);


+ 46
- 0
GCMM/MainForm.cs View File

@@ -51,7 +51,9 @@ namespace GCMM
private void playbtn_Click(object sender, EventArgs e)
{
if (playbtn.ForeColor == Color.Green) return; //Disabled
if (!BeginWork()) return;
PatchGame();
EndWork();
}

private void settingsbtn_Click(object sender, EventArgs e)
@@ -63,7 +65,51 @@ namespace GCMM

private void modlist_SelectedIndexChanged(object sender, EventArgs e)
{
if (working) return;
switch (modlist.SelectedItems.Count)
{
case 0:
modinfobox.Text = "";
UpdateButton(installbtn, false);
UpdateButton(uninstallbtn, false);
break;
case 1:
default:
installbtn.Text = "Install mod";
UpdateButton(installbtn, false);
UpdateButton(uninstallbtn, false);
foreach (ListViewItem item in modlist.SelectedItems)
{
var mod = mods[item.Name];
if (modlist.SelectedItems.Count == 1)
modinfobox.Text = mod.Description?.Replace("\n", Environment.NewLine);
else
modinfobox.Text = modlist.SelectedItems.Count + " mods selected";
if (mod.DownloadURL != null && !(mod.LatestVersion <= mod.Version))
{
UpdateButton(installbtn, true);
if (mod.Version != null)
installbtn.Text = "Update mod";
else
installbtn.Text = "Install mod";
}
if (mod.Version != null)
UpdateButton(uninstallbtn, true);
}
break;
}
}

private async void installbtn_Click(object sender, EventArgs e)
{
if (installbtn.ForeColor == Color.Green) return; //Disabled
if (!BeginWork()) return;
foreach (ListViewItem item in modlist.SelectedItems)
{
if (item.Group.Name == "installed") continue;
await InstallMod(mods[item.Name]);
}
EndWork();
}
}
}

+ 58
- 0
GCMM/MainModInstaller.cs View File

@@ -0,0 +1,58 @@
using GCMM.Properties;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace GCMM
{
partial class MainForm
{
public async Task InstallMod(ModInfo mod)
{
if (mod.DownloadURL == null) return;
if (!File.Exists(Settings.Default.GamePath + @"\Gamecraft.exe"))
{
MessageBox.Show("Gamecraft not found. Set the correct path in Settings.");
return;
}
var tmp = Directory.CreateDirectory("temp");
var plugins = Directory.CreateDirectory(Settings.Default.GamePath + @"\Plugins");
string tmppath = tmp.FullName + "\\" + mod.Name;
using (var client = GetClient())
{
await client.DownloadFileTaskAsync(mod.DownloadURL, tmppath);
string disposition = client.ResponseHeaders["Content-Disposition"];
string filename = disposition.Substring(disposition.IndexOf("filename=") + 10).Replace("\"", "");
if (filename.EndsWith(".dll"))
File.Move(tmppath, plugins.FullName + "\\" + filename);
else if (filename.EndsWith(".zip"))
{
bool pluginOnly = true;
using (var archive = ZipFile.OpenRead(tmppath))
{
foreach (var entry in archive.Entries)
{
if (entry.FullName == "Plugins/")
{
pluginOnly = false;
break;
}
}
archive.ExtractToDirectory(pluginOnly ? plugins.FullName : Settings.Default.GamePath, true);
}
}
else
{
MessageBox.Show("Don't know how to install file: " + filename);
return;
}
GetInstalledMods(); //Update list
}
}
}
}

GCMM/MainModder.cs → GCMM/MainModList.cs View File

@@ -5,7 +5,9 @@ using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
@@ -23,7 +25,7 @@ namespace GCMM
{
var an = AssemblyName.GetAssemblyName(modPath);
if (an.Name == "0Harmony") continue;
AddUpdateModInList(new ModInfo { Name = an.Name, Version = an.Version.ToString(), LastUpdated = File.GetLastWriteTime(modPath) });
AddUpdateModInList(new ModInfo { Name = an.Name, Version = an.Version, LastUpdated = File.GetLastWriteTime(modPath) });
}
catch (BadImageFormatException)
{ //Not a .NET assembly
@@ -33,7 +35,7 @@ namespace GCMM

public async void GetAvailableMods()
{
string reposURL = "/api/v1/repos/search?sort=updated&order=desc";
/*string reposURL = "/api/v1/repos/search?sort=updated&order=desc";
using (var client = GetClient())
{
var obj = JObject.Parse(await client.DownloadStringTaskAsync(reposURL));
@@ -49,6 +51,17 @@ namespace GCMM
if (await FetchModInfo(mod)) //If it's actually a mod
AddUpdateModInList(mod);
}
}*/
foreach (string line in File.ReadLines("modlist.txt"))
{
var sp = line.Split('\t');
var mod = new ModInfo
{
Author = sp[0],
Name = sp[1]
};
if (await FetchModInfo(mod)) //If it's actually a mod
AddUpdateModInList(mod);
}
}

@@ -57,17 +70,25 @@ namespace GCMM
string repoURL = "/api/v1/repos/" + mod.Author + "/" + mod.Name + "/releases";
using (var client = GetClient())
{
var obj = JArray.Parse(await client.DownloadStringTaskAsync(repoURL));
var release = obj.FirstOrDefault(rel => !(bool)rel["prerelease"] && !(bool)rel["draft"]);
var arr = JArray.Parse(await client.DownloadStringTaskAsync(repoURL));
var release = arr.FirstOrDefault(rel => !(bool)rel["prerelease"] && !(bool)rel["draft"]);
if (release == null)
return false;
else
{
if (release["assets"].Count() == 1)
mod.DownloadURL = release["assets"].First["browser_download_url"].ToString();
mod.LastUpdated = (DateTime)release["published_at"];
mod.LatestVersion = release["tag_name"].ToString().Replace("v", "");
return true;
mod.LastUpdated = (DateTime)release["published_at"];
var ver = release["tag_name"].ToString().Replace("v", "").Split('.').Select(str => int.Parse(str)).ToArray();
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));
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;
}
}

@@ -84,8 +105,10 @@ namespace GCMM
omod.Version = mod.Version ?? omod.Version;
omod.LatestVersion = mod.LatestVersion ?? omod.LatestVersion;
omod.LastUpdated = mod.LastUpdated == default ? omod.LastUpdated : mod.LastUpdated;
omod.Description = mod.Description ?? omod.Description;
omod.DownloadURL = mod.DownloadURL ?? omod.DownloadURL;
items[1].Text = omod.Author ?? "";
items[2].Text = omod.Version ?? omod.LatestVersion;
items[2].Text = (omod.Version ?? omod.LatestVersion)?.ToString();
items[3].Text = omod.LastUpdated.ToString();
item.Group = omod.Installed ? modlist.Groups["installed"] : modlist.Groups["available"];
if (mod.Version != mod.LatestVersion)
@@ -94,7 +117,7 @@ namespace GCMM
else
{
mods.Add(mod.Name, mod);
var item = new ListViewItem(new[] { mod.Name, mod.Author ?? "", mod.Version ?? mod.LatestVersion ?? "", mod.LastUpdated.ToString() }, modlist.Groups[mod.Installed ? "installed" : "available"]);
var item = new ListViewItem(new[] { mod.Name, mod.Author ?? "", (mod.Version ?? mod.LatestVersion)?.ToString() ?? "", mod.LastUpdated.ToString() }, modlist.Groups[mod.Installed ? "installed" : "available"]);
item.Name = mod.Name;
modlist.Items.Add(item);
}

+ 0
- 5
GCMM/MainPatcher.cs View File

@@ -15,7 +15,6 @@ namespace GCMM
{
partial class MainForm
{

public bool? CheckIfPatched()
{
if (!File.Exists(Settings.Default.GamePath + @"\IPA.exe"))
@@ -48,10 +47,6 @@ namespace GCMM

public async void PatchGame()
{
UpdateButton(playbtn, false);
UpdateButton(installbtn, false);
UpdateButton(uninstallbtn, false);
UpdateButton(settingsbtn, false);
if (!CheckIfPatched().HasValue)
{
if (MessageBox.Show("The patcher (GCIPA) is not found. It will be downloaded from https://git.exmods.org/modtainers/GCIPA/releases and ran to patch the game.", "Patcher download needed", MessageBoxButtons.OKCancel)


+ 24
- 0
GCMM/MainUtils.cs View File

@@ -93,5 +93,29 @@ namespace GCMM
client.BaseAddress = "https://git.exmods.org";
return client;
}

private bool working = false;
/// <summary>
/// Some simple "locking", only allow one operation at a time
/// </summary>
/// <returns>Whether the work can begin</returns>
public bool BeginWork()
{
if (working) return false;
working = true;
UpdateButton(playbtn, false);
UpdateButton(installbtn, false);
UpdateButton(uninstallbtn, false);
UpdateButton(settingsbtn, false);
return true;
}

public void EndWork()
{
working = false;
UpdateButton(playbtn, true);
UpdateButton(settingsbtn, true);
modlist_SelectedIndexChanged(modlist, null);
}
}
}

+ 2
- 2
GCMM/ModInfo.cs View File

@@ -12,8 +12,8 @@ namespace GCMM
/// <summary>
/// Can be null.
/// </summary>
public string Version { get; set; }
public string LatestVersion { get; set; }
public Version Version { get; set; }
public Version LatestVersion { get; set; }
/// <summary>
/// Can be null.
/// </summary>


+ 42
- 0
GCMM/ZipArchiveExtensions.cs View File

@@ -0,0 +1,42 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace GCMM
{
public static class ZipArchiveExtensions
{ //https://stackoverflow.com/a/14795752/2703239
public static void ExtractToDirectory(this ZipArchive archive, string destinationDirectoryName, bool overwrite)
{
if (!overwrite)
{
archive.ExtractToDirectory(destinationDirectoryName);
return;
}

DirectoryInfo di = Directory.CreateDirectory(destinationDirectoryName);
string destinationDirectoryFullPath = di.FullName;

foreach (ZipArchiveEntry file in archive.Entries)
{
string completeFileName = Path.GetFullPath(Path.Combine(destinationDirectoryFullPath, file.FullName));

if (!completeFileName.StartsWith(destinationDirectoryFullPath, StringComparison.OrdinalIgnoreCase))
{
throw new IOException("Trying to extract file outside of destination directory. See this link for more info: https://snyk.io/research/zip-slip-vulnerability");
}

if (file.Name == "")
{// Assuming Empty for Directory
Directory.CreateDirectory(Path.GetDirectoryName(completeFileName));
continue;
}
file.ExtractToFile(completeFileName, true);
}
}
}
}

+ 9
- 0
GCMM/modlist.txt View File

@@ -0,0 +1,9 @@
NGnius GamecraftRichPresenceMod
SnakesOnAGame GamecraftScripting
NGnius Pixi
modtainers GamecraftModdingAPI
ExtraCommands extracommands
NorbiPeti GCDC
NorbiPeti GCMC
NorbiPeti BlockMod
NGnius leadercraft

Loading…
Cancel
Save