2020-06-15 19:11:05 +00:00
using GCMM.Properties ;
2020-06-15 21:17:49 +00:00
using Newtonsoft.Json.Linq ;
2020-06-15 19:11:05 +00:00
using System ;
2020-06-15 21:17:49 +00:00
using System.Diagnostics ;
2020-06-15 19:11:05 +00:00
using System.Drawing ;
using System.IO ;
2020-06-15 21:17:49 +00:00
using System.IO.Compression ;
2020-06-15 19:11:05 +00:00
using System.Linq ;
2020-06-15 21:17:49 +00:00
using System.Net ;
using System.Reflection ;
2020-06-15 19:11:05 +00:00
using System.Text.RegularExpressions ;
using System.Threading.Tasks ;
using System.Windows.Forms ;
namespace GCMM
{
public partial class MainForm : Form
{
public MainForm ( )
{
InitializeComponent ( ) ;
}
private void Form1_Load ( object sender , EventArgs e )
{
modlist . Items . Clear ( ) ;
UpdateButton ( installbtn , false ) ;
modinfobox . Text = "" ;
if ( string . IsNullOrWhiteSpace ( Settings . Default . GamePath ) )
{
Settings . Default . GamePath = GetGameFolder ( ) ;
if ( string . IsNullOrWhiteSpace ( Settings . Default . GamePath ) )
Settings . Default . GamePath = SelectGameFolder ( ) ;
else
MessageBox . Show ( "Found game at " + Settings . Default . GamePath ) ;
Settings . Default . Save ( ) ;
}
2020-06-15 21:17:49 +00:00
if ( string . IsNullOrWhiteSpace ( Settings . Default . GamePath ) )
{
status . Text = "Status: Game not found" ;
return ;
}
CheckIfPatched ( ) ;
GetInstalledMods ( ) ;
2020-06-16 13:45:04 +00:00
GetAvailableMods ( ) ;
2020-06-15 19:11:05 +00:00
}
public void UpdateButton ( Button button , bool enabled )
{
if ( enabled )
{
button . ForeColor = Color . Lime ;
button . FlatAppearance . MouseOverBackColor = Color . FromArgb ( 0 , 40 , 0 ) ;
button . FlatAppearance . MouseDownBackColor = Color . Green ;
}
else
{
button . ForeColor = Color . Green ;
button . FlatAppearance . MouseOverBackColor = Color . Black ;
button . FlatAppearance . MouseDownBackColor = Color . Black ;
}
}
public string GetGameFolder ( )
{
string libs ;
if ( Environment . OSVersion . Platform = = PlatformID . Win32NT )
libs = @"C:\Program Files (x86)\Steam\steamapps\libraryfolders.vdf" ;
else
return null ;
foreach ( var line in File . ReadAllLines ( libs ) . Concat ( new [ ] { @"C:\Program Files (x86)\Steam\" } ) )
{
var regex = new Regex ( "\\t\"\\d+\"\\t\\t\"(.+)\"" ) ;
var match = regex . Match ( line ) ;
if ( ! match . Success )
continue ;
string library = match . Groups [ 1 ] . Value . Replace ( "\\\\" , "\\" ) ;
library + = @"\steamapps\common\" ;
if ( File . Exists ( library + @"Gamecraft\Gamecraft.exe" ) )
return library + "Gamecraft" ;
if ( File . Exists ( library + @"RobocraftX\Gamecraft.exe" ) )
return library + "RobocraftX" ;
}
return libs ;
}
public string SelectGameFolder ( )
{
var ofd = new OpenFileDialog ( ) ;
ofd . Filter = "Gamecraft executable|Gamecraft.exe" ;
ofd . Title = "Game location" ;
ofd . InitialDirectory = @"C:\Program Files (x86)\Steam\steamapps\common\" ;
ofd . CheckFileExists = true ;
ofd . ShowDialog ( ) ;
if ( string . IsNullOrWhiteSpace ( ofd . FileName ) )
return null ;
return Directory . GetParent ( ofd . FileName ) . FullName ;
}
2020-06-15 21:17:49 +00:00
public void GetInstalledMods ( )
2020-06-15 19:11:05 +00:00
{
2020-06-15 21:17:49 +00:00
foreach ( var mod in Directory . GetFiles ( Settings . Default . GamePath + @"\Plugins" , "*.dll" ) )
{
try
{
var an = AssemblyName . GetAssemblyName ( mod ) ;
if ( an . Name = = "0Harmony" ) continue ;
2020-06-16 13:45:04 +00:00
var item = new ListViewItem ( new [ ] { an . Name , "" , an . Version . ToString ( ) , File . GetLastWriteTime ( mod ) . ToString ( ) } , modlist . Groups [ "installed" ] ) ;
item . Name = an . Name ;
modlist . Items . Add ( item ) ;
2020-06-15 21:17:49 +00:00
}
catch ( BadImageFormatException )
{ //Not a .NET assembly
}
}
}
2020-06-15 19:11:05 +00:00
2020-06-15 21:17:49 +00:00
public bool? CheckIfPatched ( )
{
if ( ! File . Exists ( Settings . Default . GamePath + @"\IPA.exe" ) )
{
2020-06-16 13:45:04 +00:00
status . Text = "Status: Patcher missing\nClicking Play will install it" ;
2020-06-15 21:17:49 +00:00
return null ;
}
2020-06-16 13:45:04 +00:00
string nopatch = "Status: Unpatched\nClicking Play patches it" ;
2020-06-15 21:17:49 +00:00
if ( ! Directory . Exists ( Settings . Default . GamePath + @"\IPA\Backups\Gamecraft" ) )
{
status . Text = nopatch ;
return false ;
}
string backup = Directory . EnumerateDirectories ( Settings . Default . GamePath + @"\IPA\Backups\Gamecraft" ) . OrderByDescending ( s = > s ) . FirstOrDefault ( ) ;
if ( backup = = null )
{
status . Text = nopatch ;
return false ;
}
if ( File . GetLastWriteTime ( Settings . Default . GamePath + @"\Gamecraft_Data\Managed\Assembly-CSharp.dll" )
2020-06-16 13:45:04 +00:00
> //If the file was updated at least 2 minutes after patching
Directory . GetLastWriteTime ( backup ) . AddMinutes ( 2 ) )
2020-06-15 21:17:49 +00:00
{
status . Text = nopatch ;
return false ;
}
status . Text = "Status: Patched" ;
return true ;
}
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 )
= = DialogResult . Cancel )
return ;
2020-06-16 13:45:04 +00:00
string releases = "/api/v1/repos/modtainers/GCIPA/releases" ;
2020-06-15 21:17:49 +00:00
string url ;
this . status . Text = "Status: Patching..." ;
2020-06-16 13:45:04 +00:00
using ( WebClient client = await GetClient ( ) )
2020-06-15 21:17:49 +00:00
{
2020-06-16 13:45:04 +00:00
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 ) ;
}
2020-06-15 21:17:49 +00:00
}
bool? status = CheckIfPatched ( ) ;
if ( ! status . HasValue ) //Make sure it actually worked
return ;
if ( ! status . Value )
{
var psi = new ProcessStartInfo ( Settings . Default . GamePath + @"\IPA.exe" , "Gamecraft.exe --nowait" ) ;
psi . UseShellExecute = false ;
psi . RedirectStandardError = true ;
psi . RedirectStandardOutput = true ;
psi . WorkingDirectory = Settings . Default . GamePath ;
psi . 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 ;
}
else
CheckStartGame ( null , null ) ;
}
private void CheckStartGame ( object sender , EventArgs e )
{
Action act = ( ) = >
{
if ( ( sender as Process ) . ExitCode ! = 0 )
{
status . Text = "Status: Patching failed" ;
return ;
}
if ( CheckIfPatched ( ) ? ? false )
Process . Start ( "steam://run/1078000/" ) ;
} ;
if ( InvokeRequired )
Invoke ( act ) ;
}
2020-06-16 13:45:04 +00:00
public async void GetAvailableMods ( )
{
string reposURL = "/api/v1/repos/search?sort=updated&order=desc" ;
using ( var client = await GetClient ( ) )
{
var obj = JObject . Parse ( await client . DownloadStringTaskAsync ( reposURL ) ) ;
if ( ! ( bool ) obj [ "ok" ] ) return ;
foreach ( var repo in obj [ "data" ] )
{
string name = repo [ "name" ] . ToString ( ) ;
if ( modlist . Items . ContainsKey ( name ) )
{
var item = modlist . Items [ name ] ;
var si = item . SubItems ;
si [ 1 ] = new ListViewItem . ListViewSubItem ( item , repo [ "owner" ] [ "username" ] . ToString ( ) ) ;
}
else
{
var item = new ListViewItem ( new [ ] { name , repo [ "owner" ] [ "username" ] . ToString ( ) , "" , ( ( DateTime ) repo [ "updated_at" ] ) . ToString ( ) } , modlist . Groups [ "available" ] ) ;
item . Name = name ;
modlist . Items . Add ( item ) ;
}
}
}
}
public async Task < WebClient > GetClient ( )
{
var client = new WebClient ( ) ;
if ( ! Settings . Default . UseProxy )
client . Proxy = null ;
client . Headers . Clear ( ) ;
client . Headers [ HttpRequestHeader . Accept ] = "application/json" ;
/ * client . Headers [ HttpRequestHeader . Host ] = "git.exmods.org" ;
var addr = ( await Dns . GetHostAddressesAsync ( "git.exmods.org" ) ) . Where ( ip = > ip . AddressFamily = = System . Net . Sockets . AddressFamily . InterNetwork ) . First ( ) ;
client . BaseAddress = "https://" + addr ; * /
client . BaseAddress = "https://git.exmods.org" ;
return client ;
}
2020-06-15 21:17:49 +00:00
private void playbtn_Click ( object sender , EventArgs e )
{
if ( playbtn . ForeColor = = Color . Green ) return ; //Disabled
PatchGame ( ) ;
2020-06-15 19:11:05 +00:00
}
private void settingsbtn_Click ( object sender , EventArgs e )
{
2020-06-15 21:17:49 +00:00
if ( settingsbtn . ForeColor = = Color . Green ) return ; //Disabled
2020-06-15 19:11:05 +00:00
var sf = new SettingsForm ( ) ;
sf . ShowDialog ( this ) ;
}
2020-06-16 13:45:04 +00:00
private void modlist_SelectedIndexChanged ( object sender , EventArgs e )
{
}
2020-06-15 19:11:05 +00:00
}
}