NorbiPeti
b4d64c50d0
Fixed the game folder method returning the library file Checking the game's exe when starting Added support for the preview branch of the game Added support for preview versions of mods
156 lines
6.7 KiB
C#
156 lines
6.7 KiB
C#
using GCMM.Properties;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
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;
|
|
|
|
namespace GCMM
|
|
{
|
|
partial class MainForm
|
|
{
|
|
|
|
public void GetInstalledMods()
|
|
{
|
|
foreach (var modPath in Directory.GetFiles(GamePath(@"\Plugins"), "*.dll"))
|
|
{
|
|
try
|
|
{
|
|
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) });
|
|
}
|
|
catch (BadImageFormatException)
|
|
{ //Not a .NET assembly
|
|
}
|
|
}
|
|
}
|
|
|
|
public async void GetAvailableMods()
|
|
{
|
|
bool preview = GetExe()?.Contains("Preview") ?? false;
|
|
using (var client = GetClient())
|
|
{
|
|
string str = await client.DownloadStringTaskAsync("https://exmods.org/mods/modlist.tsv");
|
|
foreach (string line in str.Trim().Split('\n'))
|
|
{
|
|
var sp = line.Split('\t');
|
|
if (sp.Length < 2) continue;
|
|
var mod = new ModInfo
|
|
{
|
|
Author = sp[0].Trim(),
|
|
Name = sp[1].Trim()
|
|
};
|
|
if (await FetchModInfo(mod, preview)) //If it's actually a mod
|
|
AddUpdateModInList(mod);
|
|
}
|
|
}
|
|
}
|
|
|
|
public async Task<bool> FetchModInfo(ModInfo mod, bool preview)
|
|
{
|
|
string repoURL = "/api/v1/repos/" + mod.Author + "/" + mod.Name + "/releases";
|
|
using (var client = GetClient())
|
|
{
|
|
var arr = JArray.Parse(await client.DownloadStringTaskAsync(repoURL));
|
|
var release = arr.FirstOrDefault(rel =>
|
|
{
|
|
if ((bool) rel["prerelease"] || (bool) rel["draft"])
|
|
return false;
|
|
var vs = rel["tag_name"].ToString();
|
|
int ind = vs.IndexOf('-');
|
|
if (ind != -1)
|
|
{
|
|
if (vs.Substring(ind + 1).Equals("preview", StringComparison.InvariantCultureIgnoreCase)
|
|
&& !preview)
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
if (release == null)
|
|
return false;
|
|
var verstr = release["tag_name"].ToString().Replace("v", "");
|
|
int index = verstr.IndexOf('-');
|
|
if (index != -1)
|
|
verstr = verstr.Substring(0, index);
|
|
|
|
JToken asset;
|
|
if (release["assets"].Count() == 1)
|
|
asset = release["assets"].First;
|
|
else
|
|
asset = release["assets"].FirstOrDefault(token =>
|
|
{
|
|
string name = token["name"].ToString();
|
|
return name == mod.Name + ".dll" || name == mod.Name + ".zip";
|
|
});
|
|
|
|
mod.DownloadURL = asset?["browser_download_url"]?.ToString();
|
|
mod.LastUpdated = (DateTime)release["published_at"];
|
|
|
|
var ver = verstr.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));
|
|
mod.UpdateDetails = release["name"] + "\n\n" + release["body"].ToString();
|
|
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;
|
|
}
|
|
}
|
|
|
|
public void AddUpdateModInList(ModInfo mod)
|
|
{
|
|
if (mods.ContainsKey(mod.Name) ^ modlist.Items.ContainsKey(mod.Name)) //The ListView's keys aren't case sensitive
|
|
throw new InvalidOperationException("The mod isn't present in one of the two places: " + mod.Name);
|
|
ListViewItem item;
|
|
if (modlist.Items.ContainsKey(mod.Name))
|
|
{
|
|
var omod = mods[mod.Name];
|
|
item = modlist.Items[mod.Name];
|
|
var items = item.SubItems;
|
|
omod.Author = mod.Author ?? omod.Author;
|
|
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;
|
|
omod.UpdateDetails = mod.UpdateDetails ?? omod.UpdateDetails;
|
|
items[1].Text = omod.Author ?? "";
|
|
items[2].Text = (omod.Version ?? omod.LatestVersion)?.ToString();
|
|
items[3].Text = omod.LastUpdated.ToString();
|
|
item.Group = omod.Installed ? modlist.Groups["installed"] : modlist.Groups["available"];
|
|
mod = omod;
|
|
}
|
|
else
|
|
{
|
|
mods.Add(mod.Name, mod);
|
|
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);
|
|
}
|
|
if (mod.LatestVersion != null && mod.Version != null && mod.Version < mod.LatestVersion)
|
|
item.ForeColor = Color.Blue;
|
|
else
|
|
item.ForeColor = modlist.ForeColor;
|
|
}
|
|
|
|
public void RemoveModFromList(ModInfo mod)
|
|
{
|
|
if (mods.Remove(mod.Name))
|
|
modlist.Items.RemoveByKey(mod.Name);
|
|
}
|
|
}
|
|
}
|