diff --git a/.gitignore b/.gitignore
index fb2c22e..c6244ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -352,3 +352,6 @@ MigrationBackup/
# Visual Studio Code folder
.vscode/
+
+# Mac's DS_Stores
+.DS_Store
diff --git a/AM2RLauncher/AM2RLauncher.Gtk/Program.cs b/AM2RLauncher/AM2RLauncher.Gtk/Program.cs
index c3652c7..8417535 100644
--- a/AM2RLauncher/AM2RLauncher.Gtk/Program.cs
+++ b/AM2RLauncher/AM2RLauncher.Gtk/Program.cs
@@ -56,7 +56,10 @@ namespace AM2RLauncher.Gtk
private static void GTKLauncher_UnhandledException(object sender, Eto.UnhandledExceptionEventArgs e)
{
log.Error("An unhandled exception has occurred: \n*****Stack Trace*****\n\n" + e.ExceptionObject.ToString());
- MessageBox.Show(Language.Text.UnhandledException + "\n*****Stack Trace*****\n\n" + e.ExceptionObject.ToString(), "GTK", MessageBoxType.Error);
+ Application.Instance.Invoke(new Action(() =>
+ {
+ MessageBox.Show(Language.Text.UnhandledException + "\n*****Stack Trace*****\n\n" + e.ExceptionObject.ToString(), "GTK", MessageBoxType.Error);
+ }));
}
// This is a duplicate of CrossPlatformOperations.GenerateCurrentPath, because trying to invoke that would cause a crash due to currentPlatform not being initialized.
diff --git a/AM2RLauncher/AM2RLauncher.Mac/AM2RLauncher.Mac.csproj b/AM2RLauncher/AM2RLauncher.Mac/AM2RLauncher.Mac.csproj
new file mode 100644
index 0000000..c95dd8b
--- /dev/null
+++ b/AM2RLauncher/AM2RLauncher.Mac/AM2RLauncher.Mac.csproj
@@ -0,0 +1,43 @@
+
+
+
+ WinExe
+ net6.0
+ osx-x64
+ LatestMajor
+
+
+
+ 4
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ Resources.resx
+
+
+
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AM2RLauncher/AM2RLauncher.Mac/Icon.icns b/AM2RLauncher/AM2RLauncher.Mac/Icon.icns
new file mode 100644
index 0000000..f84187f
Binary files /dev/null and b/AM2RLauncher/AM2RLauncher.Mac/Icon.icns differ
diff --git a/AM2RLauncher/AM2RLauncher.Mac/Info.plist b/AM2RLauncher/AM2RLauncher.Mac/Info.plist
new file mode 100644
index 0000000..130f17d
--- /dev/null
+++ b/AM2RLauncher/AM2RLauncher.Mac/Info.plist
@@ -0,0 +1,20 @@
+
+
+
+
+ CFBundleName
+ AM2RLauncher
+ CFBundleIdentifier
+ com.example.AM2RLauncher
+ CFBundleShortVersionString
+ 1.0
+ LSMinimumSystemVersion
+ 10.12
+ CFBundleDevelopmentRegion
+ en
+ NSHumanReadableCopyright
+
+ CFBundleIconFile
+ Icon.icns
+
+
diff --git a/AM2RLauncher/AM2RLauncher.Mac/Program.cs b/AM2RLauncher/AM2RLauncher.Mac/Program.cs
new file mode 100644
index 0000000..6cce445
--- /dev/null
+++ b/AM2RLauncher/AM2RLauncher.Mac/Program.cs
@@ -0,0 +1,83 @@
+using Eto.Forms;
+using log4net;
+using log4net.Config;
+using System;
+using System.IO;
+using System.Reflection;
+
+namespace AM2RLauncher.Mac
+{
+ ///
+ /// The main class for the Mac project.
+ ///
+ class MainClass
+ {
+ ///
+ /// The logger for , used to write any caught exceptions.
+ ///
+ private static readonly ILog log = LogManager.GetLogger(typeof(MainForm));
+
+ ///
+ /// The main method for the Mac project.
+ ///
+ [STAThread]
+ public static void Main(string[] args)
+ {
+ string launcherDataPath = GenerateCurrentPath();
+
+ // Make sure first, ~/.local/share/AM2RLauncher exists
+ if (!Directory.Exists(launcherDataPath))
+ Directory.CreateDirectory(launcherDataPath);
+
+ // Now, see if log4netConfig exists, if not write it again.
+ if (!File.Exists(launcherDataPath + "/log4net.config"))
+ File.WriteAllText(launcherDataPath + "/log4net.config", Properties.Resources.log4netContents.Replace("${DATADIR}", launcherDataPath));
+
+ // Configure logger
+ XmlConfigurator.Configure(new FileInfo(launcherDataPath + "/log4net.config"));
+
+ try
+ {
+ Application MacLauncher = new Application(Eto.Platforms.Mac64);
+ LauncherUpdater.Main();
+ MacLauncher.UnhandledException += MacLauncher_UnhandledException;
+ MacLauncher.Run(new MainForm());
+ }
+ catch (Exception e)
+ {
+ log.Error("An unhandled exception has occurred: \n*****Stack Trace*****\n\n" + e.StackTrace.ToString());
+ Console.WriteLine(Language.Text.UnhandledException + "\n" + e.Message + "\n*****Stack Trace*****\n\n" + e.StackTrace.ToString());
+ Console.WriteLine("Check the logs at " + launcherDataPath + " for more info!");
+ }
+ //new Application(Eto.Platforms.Mac64).Run(new MainForm());
+ }
+
+ ///
+ /// This method gets fired when an unhandled excpetion occurs in .
+ ///
+ private static void MacLauncher_UnhandledException(object sender, Eto.UnhandledExceptionEventArgs e)
+ {
+ log.Error("An unhandled exception has occurred: \n*****Stack Trace*****\n\n" + e.ExceptionObject.ToString());
+ /*Application.Instance.Invoke(new Action(() =>
+ {
+ MessageBox.Show(Language.Text.UnhandledException + "\n*****Stack Trace*****\n\n" + e.ExceptionObject.ToString(), "Mac", MessageBoxType.Error);
+ }));*/
+ }
+
+ // This is a duplicate of CrossPlatformOperations.GenerateCurrentPath, because trying to invoke that would cause a crash due to currentPlatform not being initialized.
+ private static string GenerateCurrentPath()
+ {
+ string NIXHOME = Environment.GetEnvironmentVariable("HOME");
+ //Mac has the Path at HOME/Library/AM2RLauncher
+ string macPath = NIXHOME + "/Library/AM2RLauncher";
+ try
+ {
+ Directory.CreateDirectory(macPath);
+ return macPath;
+ }
+ catch { }
+
+ return Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
+ }
+ }
+}
diff --git a/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.Designer.cs b/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.Designer.cs
new file mode 100644
index 0000000..641e315
--- /dev/null
+++ b/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.Designer.cs
@@ -0,0 +1,56 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AM2RLauncher.Mac.Properties {
+ using System;
+ using System.Reflection;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static System.Resources.ResourceManager resourceMan;
+
+ private static System.Globalization.CultureInfo resourceCulture;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("AM2RLauncher.Mac.Properties.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ internal static string log4netContents {
+ get {
+ return ResourceManager.GetString("log4netContents", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.resx b/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.resx
new file mode 100644
index 0000000..a2cff8e
--- /dev/null
+++ b/AM2RLauncher/AM2RLauncher.Mac/Properties/Resources.resx
@@ -0,0 +1,139 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ <log4net>
+ <root>
+ <level value="ALL" />
+ <appender-ref ref="file" />
+ </root>
+ <appender name="file" type="log4net.Appender.RollingFileAppender">
+ <file value="${DATADIR}/Logs/AM2RLauncher.log" />
+ <appendToFile value="true" />
+ <rollingStyle value="Once" />
+ <maxSizeRollBackups value="7" />
+ <maximumFileSize value="3MB" />
+ <staticLogFileName value="true" />
+ <layout type="log4net.Layout.PatternLayout">
+ <conversionPattern value="%date [%thread] %level %logger - %message%newline" />
+ </layout>
+ </appender>
+</log4net>
+
+
\ No newline at end of file
diff --git a/AM2RLauncher/AM2RLauncher.sln b/AM2RLauncher/AM2RLauncher.sln
index 836a33c..e616f49 100644
--- a/AM2RLauncher/AM2RLauncher.sln
+++ b/AM2RLauncher/AM2RLauncher.sln
@@ -9,6 +9,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AM2RLauncher.Gtk", "AM2RLau
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AM2RLauncher.Wpf", "AM2RLauncher.Wpf\AM2RLauncher.Wpf.csproj", "{8A162932-BAA3-429A-84C4-B93A1C85DDE3}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AM2RLauncher.Mac", "AM2RLauncher.Mac\AM2RLauncher.Mac.csproj", "{6F240F19-144E-4704-A16A-8FDAC3867EC9}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -27,6 +29,10 @@ Global
{8A162932-BAA3-429A-84C4-B93A1C85DDE3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8A162932-BAA3-429A-84C4-B93A1C85DDE3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8A162932-BAA3-429A-84C4-B93A1C85DDE3}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6F240F19-144E-4704-A16A-8FDAC3867EC9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6F240F19-144E-4704-A16A-8FDAC3867EC9}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6F240F19-144E-4704-A16A-8FDAC3867EC9}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6F240F19-144E-4704-A16A-8FDAC3867EC9}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/AM2RLauncher/AM2RLauncher/CrossPlatformOperations.cs b/AM2RLauncher/AM2RLauncher/CrossPlatformOperations.cs
index 5df6d4e..b26daa5 100644
--- a/AM2RLauncher/AM2RLauncher/CrossPlatformOperations.cs
+++ b/AM2RLauncher/AM2RLauncher/CrossPlatformOperations.cs
@@ -36,9 +36,9 @@ namespace AM2RLauncher
public static readonly string NIXHOME = Environment.GetEnvironmentVariable("HOME");
///
- /// Path to the Config folder on *Nix-based systems.
+ /// Path to the Config folder on Linux-based systems.
///
- public static readonly string NIXXDGCONFIG = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME");
+ public static readonly string LINUXXDGCONFIG = Environment.GetEnvironmentVariable("XDG_CONFIG_HOME");
///
/// Current Path where the Launcher is located. For more info, check .
@@ -67,8 +67,18 @@ namespace AM2RLauncher
"https://gitlab.com/am2r-community-developers/AM2R-Autopatcher-Linux.git"
};
}
+ else if (currentPlatform.IsMac)
+ {
+ return new List
+ {
+ "https://github.com/Miepee/AM2R-Autopatcher-Mac.git",
+ "https://github.com/Miepee/AM2R-Autopatcher-Mac.git" //TODO: make mac official, put this on gitlab
+ };
+
+ }
else // Should never occur, but...
{
+ log.Error(currentPlatform.ID + " has no mirror lists!");
return new List();
}
}
@@ -78,8 +88,10 @@ namespace AM2RLauncher
///
/// The property to get the value from.
/// The value from as a string
+ // TODO: how often is launcherconfigpath / launcherconfigfilepath created? maybe create an extra variable for it so we don't generate it every time
public static string ReadFromConfig(string property)
{
+ log.Info($"Reading {property} from config.");
if (currentPlatform.IsWinForms)
{
// We use the configuration manager in order to read `property` from the app.config and then return it
@@ -87,11 +99,16 @@ namespace AM2RLauncher
if (appConfig == null) throw new ArgumentException("The property " + property + " could not be found.");
return appConfig.ConnectionString;
}
- if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
- // Config for nix systems will be saved in XDG_CONFIG_HOME/AM2RLauncher (or if empty, ~/.config)
+ // Config for linux systems will be saved in XDG_CONFIG_HOME/AM2RLauncher (or if empty, ~/.config)
+ // Config for mac systems will be saved in ~/Library/Preferences/AM2RLauncher
string homePath = NIXHOME;
- string launcherConfigPath = (String.IsNullOrWhiteSpace(NIXXDGCONFIG) ? (homePath + "/.config") : NIXXDGCONFIG) + "/AM2RLauncher";
+ string launcherConfigPath = "";
+ if (currentPlatform.IsGtk)
+ launcherConfigPath = (String.IsNullOrWhiteSpace(LINUXXDGCONFIG) ? (homePath + "/.config") : LINUXXDGCONFIG) + "/AM2RLauncher";
+ else if (currentPlatform.IsMac)
+ launcherConfigPath = homePath + "/Library/Preferences/AM2RLauncher";
string launcherConfigFilePath = launcherConfigPath + "/config.xml";
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
@@ -111,6 +128,8 @@ namespace AM2RLauncher
// This uses the indexer, which means, we can use the variable in order to get the property. Look at LauncherConfigXML for more info
return launcherConfig[property]?.ToString();
}
+ else
+ log.Error(currentPlatform.ID + " has no config to read from!");
return null;
}
@@ -121,6 +140,7 @@ namespace AM2RLauncher
/// The value that will be written.
public static void WriteToConfig(string property, object value)
{
+ log.Info($"Writing {value} of type {value.GetType()} to {property} to config.");
if (currentPlatform.IsWinForms)
{
// We use the configuration manager in order to read from the app.config, change the value and save it
@@ -134,11 +154,16 @@ namespace AM2RLauncher
appConfig.Save();
ConfigurationManager.RefreshSection("connectionStrings");
}
- else if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
// Config for nix systems will be saved in XDG_CONFIG_HOME/AM2RLauncher (or if empty, ~/.config)
+ // Config for mac systems will be saved in ~/Library/Preferences/AM2RLauncher
string homePath = NIXHOME;
- string launcherConfigPath = (String.IsNullOrWhiteSpace(NIXXDGCONFIG) ? (homePath + "/.config") : NIXXDGCONFIG) + "/AM2RLauncher";
+ string launcherConfigPath = "";
+ if (currentPlatform.IsGtk)
+ launcherConfigPath = (String.IsNullOrWhiteSpace(LINUXXDGCONFIG) ? (homePath + "/.config") : LINUXXDGCONFIG) + "/AM2RLauncher";
+ else if (currentPlatform.IsMac)
+ launcherConfigPath = homePath + "/Library/Preferences/AM2RLauncher";
string launcherConfigFilePath = launcherConfigPath + "/config.xml";
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
@@ -157,6 +182,8 @@ namespace AM2RLauncher
// Serialize back into the file
File.WriteAllText(launcherConfigFilePath, XML.Serializer.Serialize(launcherConfig));
}
+ else
+ log.Error(currentPlatform.ID + " has no config to write to!");
}
///
@@ -182,11 +209,16 @@ namespace AM2RLauncher
File.WriteAllText(newConfigPath, newConfigText);
}
- else if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
// Config for nix systems will be saved in XDG_CONFIG_HOME/AM2RLauncher (or if empty, ~/.config)
+ // Config for mac systems will be saved in ~/Library/Preferences/AM2RLauncher
string homePath = NIXHOME;
- string launcherConfigPath = (String.IsNullOrWhiteSpace(NIXXDGCONFIG) ? (homePath + "/.config") : NIXXDGCONFIG) + "/AM2RLauncher";
+ string launcherConfigPath = "";
+ if (currentPlatform.IsGtk)
+ launcherConfigPath = (String.IsNullOrWhiteSpace(LINUXXDGCONFIG) ? (homePath + "/.config") : LINUXXDGCONFIG) + "/AM2RLauncher";
+ else if (currentPlatform.IsMac)
+ launcherConfigPath = homePath + "/Library/Preferences/AM2RLauncher";
string launcherConfigFilePath = launcherConfigPath + "/config.xml";
XML.LauncherConfigXML launcherConfig = new XML.LauncherConfigXML();
@@ -194,6 +226,8 @@ namespace AM2RLauncher
launcherConfig = XML.Serializer.Deserialize(File.ReadAllText(launcherConfigFilePath));
File.WriteAllText(launcherConfigFilePath, XML.Serializer.Serialize(launcherConfig));
}
+ else
+ log.Error(currentPlatform.ID + " has no config to transfer over!");
}
///
@@ -206,6 +240,10 @@ namespace AM2RLauncher
Process.Start(url);
else if (currentPlatform.IsGtk)
Process.Start("xdg-open", url);
+ else if (currentPlatform.IsMac)
+ Process.Start("open", url);
+ else
+ log.Error(currentPlatform.ID + " can't open URLs!");
}
///
@@ -231,11 +269,15 @@ namespace AM2RLauncher
// Linux only opens the directory bc opening and selecting a file is pain
else if (currentPlatform.IsGtk)
Process.Start("xdg-open", $"\"{realPath}\"");
+ else if (currentPlatform.IsMac)
+ Process.Start("open", $"\"{realPath}\"");
+ else
+ log.Error(currentPlatform.ID + " can't open folders!");
}
///
/// Opens and selects it in a file explorer.
- /// Only selects on Windows, on Linux it just opens the folder. Does nothing if file doesn't exist.
+ /// Only selects on Windows and Mac, on Linux it just opens the folder. Does nothing if file doesn't exist.
///
/// Path to open.
public static void OpenFolderAndSelectFile(string path)
@@ -256,6 +298,10 @@ namespace AM2RLauncher
Process.Start("explorer.exe", $"/select, \"{realPath}\"");
else if (currentPlatform.IsGtk)
Process.Start("xdg-open", $"\"{Path.GetDirectoryName(realPath)}\"");
+ else if (currentPlatform.IsMac)
+ Process.Start("open", $"-R \"{realPath}\"");
+ else
+ log.Error(currentPlatform.ID + " can't open select files in file explorer!");
}
///
@@ -272,7 +318,7 @@ namespace AM2RLauncher
process = "cmd.exe";
arguments = "/C java -version";
}
- else if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
process = "java";
arguments = "-version";
@@ -373,7 +419,7 @@ namespace AM2RLauncher
proc.WaitForExit();
}
}
- else if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
ProcessStartInfo parameters = new ProcessStartInfo
{
@@ -405,7 +451,7 @@ namespace AM2RLauncher
proc = "cmd";
javaArgs = "/C java -jar";
}
- else if (currentPlatform.IsGtk)
+ else if (currentPlatform.IsGtk || currentPlatform.IsMac)
{
proc = "java";
javaArgs = "-jar";
@@ -497,6 +543,23 @@ namespace AM2RLauncher
log.Error($"There was an error with '{xdgDataHome}'!\n{ex.Message} {ex.StackTrace}. Falling back to defaults.");
}
}
+ else if (currentPlatform.IsMac)
+ {
+ //Mac has the Path at HOME/Library/AM2RLauncher
+ string macPath = NIXHOME + "/Library/AM2RLauncher";
+ try
+ {
+ Directory.CreateDirectory(macPath);
+ log.Info("Using default Mac CurrentPath.");
+ return macPath;
+ }
+ catch (Exception ex)
+ {
+ log.Error($"There was an error with '{macPath}'!\n{ex.Message} {ex.StackTrace}. Falling back to defaults.");
+ }
+ }
+ else
+ log.Error(currentPlatform.ID + " has no current path!");
log.Info("Something went wrong, falling back to the default CurrentPath.");
return Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
diff --git a/AM2RLauncher/AM2RLauncher/LauncherUpdater.cs b/AM2RLauncher/AM2RLauncher/LauncherUpdater.cs
index b927332..cbab196 100644
--- a/AM2RLauncher/AM2RLauncher/LauncherUpdater.cs
+++ b/AM2RLauncher/AM2RLauncher/LauncherUpdater.cs
@@ -25,6 +25,7 @@ namespace AM2RLauncher
static readonly private string oldConfigPath = CrossPlatformOperations.CURRENTPATH + "/" + CrossPlatformOperations.LAUNCHERNAME + ".oldCfg";
/// The actual Path where the executable is stored, only used for updating.
+ //TODO: for mac, this reports the path of the mac runner, not the actual .app
static readonly private string updatePath = currentPlatform.IsWinForms ? CrossPlatformOperations.CURRENTPATH : Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory);
// Load reference to logger
diff --git a/AM2RLauncher/AM2RLauncher/MainForm/HelperMethods.cs b/AM2RLauncher/AM2RLauncher/MainForm/HelperMethods.cs
index b795e60..629ef47 100644
--- a/AM2RLauncher/AM2RLauncher/MainForm/HelperMethods.cs
+++ b/AM2RLauncher/AM2RLauncher/MainForm/HelperMethods.cs
@@ -247,6 +247,7 @@ namespace AM2RLauncher.Helpers
Directory.Delete(tmpPath, true);
// If we didn't exit before, everything is fine
+ log.Info("AM2R_11 check successful!");
return IsZipAM2R11ReturnCodes.Successful;
}
diff --git a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs
index 13292f3..cc1fe4a 100644
--- a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs
+++ b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs
@@ -561,12 +561,12 @@ namespace AM2RLauncher
ProfileXML profile = Serializer.Deserialize(File.ReadAllText(modsDir + "/" + extractedName + "/profile.xml"));
// Check if the OS versions match
- if ((Platform.IsWinForms && profile.OperatingSystem != "Windows") || (Platform.IsGtk && profile.OperatingSystem != "Linux"))
+ if ((Platform.IsWinForms && profile.OperatingSystem != "Windows") || (Platform.IsGtk && profile.OperatingSystem != "Linux") || (Platform.IsMac && profile.OperatingSystem != "Mac"))
{
string currentOS = "";
if (Platform.IsWinForms) currentOS = "Windows";
else if (Platform.IsGtk) currentOS = "Linux"; // Teeeeechnically, any OS could run GTK applications as well but it'd break a lot and is thus unsupported.
-
+ else if (Platform.IsMac) currentOS = "Mac";
log.Error("Mod is for " + profile.OperatingSystem + " while current OS is " + Platform + ". Cancelling mod import.");
@@ -633,6 +633,8 @@ namespace AM2RLauncher
///
private void SettingsProfileDropDownSelectedIndexChanged(object sender, EventArgs e)
{
+ //TODO: for some reason, clearing the dropdown triggers this event on mac. Why!?
+ if (Platform.IsMac && settingsProfileDropDown.SelectedIndex == -1 && settingsProfileDropDown.Items.Count == 0) return;
log.Info("SettingsProfileDropDown.SelectedIndex has been changed to " + settingsProfileDropDown.SelectedIndex + ".");
if (settingsProfileDropDown.SelectedIndex <= 0 || settingsProfileDropDown.Items.Count == 0)
@@ -661,6 +663,7 @@ namespace AM2RLauncher
profileNotesTextArea.TextColor = colGreen;
profileNotesTextArea.Text = Language.Text.ProfileNotes + "\n" + profileList[settingsProfileDropDown.SelectedIndex].ProfileNotes;
}
+
}
///
@@ -676,6 +679,7 @@ namespace AM2RLauncher
addModButton.Enabled = false;
settingsProfileLabel.TextColor = colInactive;
settingsProfileDropDown.Enabled = false;
+ profileButton.Enabled = false;
saveButton.Enabled = false;
updateModButton.Enabled = false;
deleteModButton.Enabled = false;
@@ -741,6 +745,9 @@ namespace AM2RLauncher
/// Gets called when user selects a different item from and changes accordingly.
private void ProfileDropDownSelectedIndexChanged(object sender, EventArgs e)
{
+ //TODO: eto bug maybe? for some reason this method shouldnt even get fired when clearing a dropdown...
+ if (Platform.IsMac && profileDropDown.SelectedIndex == -1 && profileDropDown.Items.Count == 0) return;
+
profileIndex = profileDropDown.SelectedIndex;
log.Info("profileDropDown.SelectedIndex has been changed to " + profileIndex + ".");
@@ -753,7 +760,9 @@ namespace AM2RLauncher
saveWarningLabel.Visible = true;
else
saveWarningLabel.Visible = false;
+
UpdateStateMachine();
+
}
/// Gets called when user selects a different item from and writes that to the config.
diff --git a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Methods.cs b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Methods.cs
index ff27642..986cc68 100644
--- a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Methods.cs
+++ b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Methods.cs
@@ -25,12 +25,16 @@ namespace AM2RLauncher
using (var repo = new Repository(CrossPlatformOperations.CURRENTPATH + "/PatchData"))
{
// Permanently undo commits not pushed to remote
- Branch originMaster = repo.Branches["origin/master"];
+ Branch originMaster = repo.Branches.ToList().Where(b => b.FriendlyName.Contains("origin/master") || b.FriendlyName.Contains("origin/main")).FirstOrDefault();
if (originMaster == null)
{
+ log.Info("Neither branch 'master' nor branch 'main' could be found! Corrupted or invalid git repo? Deleting PatchData...");
// Directory exists, but seems corrupted, we delete it and prompt the user to download it again.
- MessageBox.Show(Language.Text.CorruptPatchData, Language.Text.ErrorWindowTitle, MessageBoxType.Error);
+ Application.Instance.Invoke(new Action(() =>
+ {
+ MessageBox.Show(Language.Text.CorruptPatchData, Language.Text.ErrorWindowTitle, MessageBoxType.Error);
+ }));
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
throw new UserCancelledException();
}
@@ -84,7 +88,10 @@ namespace AM2RLauncher
private bool IsProfileInstalled(ProfileXML profile)
{
if (Platform.IsWinForms) return File.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.exe");
- if (Platform.IsGtk) return File.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.AppImage");
+ else if (Platform.IsGtk) return File.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.AppImage");
+ else if (Platform.IsMac) return Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.app");
+
+ log.Error(Platform.ID + " can't have profiles installed!");
return false;
}
@@ -212,7 +219,7 @@ namespace AM2RLauncher
settingsProfileDropDown.Items.AddRange(profileDropDown.Items);
settingsProfileDropDown.SelectedIndex = profileDropDown.Items.Count != 0 ? 0 : -1;
- log.Info("Profiles loaded.");
+ log.Info("Loaded " + profileList.Count + " profile(s).");
// Refresh the author and version label on the main tab
if (profileList.Count > 0)
@@ -233,7 +240,7 @@ namespace AM2RLauncher
log.Info("Installing profile " + profile.Name + "...");
// Check if xdelta is installed on linux, by searching all folders in PATH
- if (Platform.IsGtk && !CrossPlatformOperations.CheckIfXdeltaIsInstalled())
+ if ((Platform.IsGtk || Platform.IsMac) && !CrossPlatformOperations.CheckIfXdeltaIsInstalled())
{
Application.Instance.Invoke(new Action(() =>
{
@@ -256,20 +263,35 @@ namespace AM2RLauncher
// This failsafe should NEVER get triggered, but Miepee's broken this too much for me to trust it otherwise.
if (Directory.Exists(profilePath))
Directory.Delete(profilePath, true);
-
-
+
// Create profile directory
Directory.CreateDirectory(profilePath);
// Switch profilePath on Gtk
if (Platform.IsGtk)
{
+ //TODO: it was just recursively deleted, is this really necessary?
if (Directory.Exists(profilePath + "/assets"))
Directory.Delete(profilePath + "/assets", true);
profilePath += "/assets";
Directory.CreateDirectory(profilePath);
}
+ else if (Platform.IsMac)
+ {
+ // Folder structure for mac is like this:
+ // am2r.app -> Contents
+ // -Frameworks (some libs)
+ // -MacOS (runner)
+ // -Resources (asset path)
+ profilePath += "/AM2R.app/Contents";
+ Directory.CreateDirectory(profilePath);
+ Directory.CreateDirectory(profilePath + "/MacOS");
+ Directory.CreateDirectory(profilePath + "/Resources");
+ profilePath += "/Resources";
+
+ log.Info("ProfileInstallstion: Created folder structure.");
+ }
// Extract 1.1
ZipFile.ExtractToDirectory(CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip", profilePath);
@@ -298,6 +320,15 @@ namespace AM2RLauncher
exe = Regex.Match(desktopContents, @"(?<=Exec=).*").Value;
log.Info("According to AppImage desktop file, using \"" + exe + "\" as game name.");
}
+ else if (Platform.IsMac)
+ {
+ datawin = "game.ios";
+ exe = "Mac_Runner";
+ }
+ else
+ {
+ log.Error(Platform.ID + " does not have valid runner / data.win names!");
+ }
log.Info("Attempting to patch in " + profilePath);
@@ -317,24 +348,31 @@ namespace AM2RLauncher
CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/AM2R.exe", dataPath + "/AM2R.xdelta", profilePath + "/" + exe);
}
}
- else if (Platform.IsGtk) // YYC and VM look exactly the same on Linux so we're all good here.
+ else if (Platform.IsGtk || Platform.IsMac) // YYC and VM look exactly the same on Linux and Mac so we're all good here.
{
CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/data.win", dataPath + "/game.xdelta", profilePath + "/" + datawin);
CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/AM2R.exe", dataPath + "/AM2R.xdelta", profilePath + "/" + exe);
// Just in case the resulting file isn't chmoddded...
Process.Start("chmod", "+x \"" + profilePath + "/" + exe + "\"").WaitForExit();
- // These are not needed by linux at all, so we delete them
+ // These are not needed by linux or Mac at all, so we delete them
File.Delete(profilePath + "/data.win");
File.Delete(profilePath + "/AM2R.exe");
File.Delete(profilePath + "/D3DX9_43.dll");
- // Move exe one directory out
- File.Move(profilePath + "/" + exe, profilePath.Substring(0, profilePath.LastIndexOf("/")) + "/" + exe);
+ // Move exe one directory out on Linux, move to MacOS folder instead on Mac
+ if (Platform.IsGtk)
+ File.Move(profilePath + "/" + exe, profilePath.Substring(0, profilePath.LastIndexOf("/")) + "/" + exe);
+ else
+ File.Move(profilePath + "/" + exe, profilePath.Replace("Resources", "MacOS") + "/" + exe);
+ }
+ else
+ {
+ log.Error(Platform.ID + " does not have patching methods!");
}
// Applied patch
- if (Platform.IsWinForms) UpdateProgressBar(66);
+ if (Platform.IsWinForms || Platform.IsMac) UpdateProgressBar(66);
else if (Platform.IsGtk) UpdateProgressBar(44); // Linux will take a bit longer, due to appimage creation
log.Info("xdelta patch(es) applied.");
@@ -388,6 +426,22 @@ namespace AM2RLauncher
if (File.Exists(profilePath + "/AM2R.AppImage")) File.Delete(profilePath + "/AM2R.AppImage");
File.Move(profilePath + "/" + "AM2R-x86_64.AppImage", profilePath + "/AM2R.AppImage");
}
+ // Mac post-process
+ else if (Platform.IsMac)
+ {
+ // Rename all songs to lowercase
+ foreach (var file in new DirectoryInfo(profilePath).GetFiles())
+ if (file.Name.EndsWith(".ogg") && !File.Exists(file.DirectoryName + "/" + file.Name.ToLower()))
+ File.Move(file.FullName, file.DirectoryName + "/" + file.Name.ToLower());
+ // Loading custom fonts crashes on Mac, so we delete those
+ Directory.Delete(profilePath + "/lang/fonts", true);
+ // Move Frameworks, Info.plist and PkgInfo over
+ HelperMethods.DirectoryCopy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/Frameworks", profilePath.Replace("Resources", "Frameworks"));
+ File.Copy(dataPath + "/Info.plist", profilePath.Replace("Resources", "") + "/Info.plist", true);
+ File.Copy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/PkgInfo", profilePath.Replace("Resources", "") + "/PkgInfo", true);
+ //Put profilePath back to what it was before
+ profilePath = profilesHomePath + "/" + profile.Name;
+ }
// Copy profile.xml so we can grab data to compare for updates later!
// tldr; check if we're in PatchData or not
@@ -428,7 +482,7 @@ namespace AM2RLauncher
return;
}
// Check if xdelta is installed on linux
- if (Platform.IsGtk && !CrossPlatformOperations.CheckIfXdeltaIsInstalled())
+ if ((Platform.IsGtk || Platform.IsMac) && !CrossPlatformOperations.CheckIfXdeltaIsInstalled())
{
// Message box show needs to be done on main thread
Application.Instance.Invoke(new Action(() =>
@@ -672,6 +726,48 @@ namespace AM2RLauncher
}
}
+ else if (Platform.IsMac)
+ {
+ // Sets the arguments to only open the game, or append the profiles save path/logs and create time based logs. Creates the folder if necessary.
+ string arguments = "AM2R.app -W";
+
+ // Game logging
+ if ((bool)profileDebugLogCheck.Checked)
+ {
+ log.Info("Performing logging setup for profile " + profile.Name + ".");
+
+ if (!Directory.Exists(logDir.FullName))
+ Directory.CreateDirectory(logDir.FullName);
+
+ if (File.Exists(logDir.FullName + "/" + profile.Name + ".txt"))
+ HelperMethods.RecursiveRollover(logDir.FullName + "/" + profile.Name + ".txt", 5);
+
+ StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt");
+
+ stream.WriteLine("AM2RLauncher " + VERSION + " log generated at " + date);
+
+ stream.Flush();
+
+ stream.Close();
+
+ arguments += " --stdout \"" + logDir.FullName + "/" + profile.Name + ".txt\" --stderr \"" + logDir.FullName + "/" + profile.Name + ".txt\"";
+ }
+
+ ProcessStartInfo proc = new ProcessStartInfo();
+
+ proc.WorkingDirectory = CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name;
+ proc.FileName = "open";
+ proc.Arguments = arguments;
+
+ log.Info("CWD of Profile is " + proc.WorkingDirectory);
+
+ using (var p = Process.Start(proc))
+ {
+ p.WaitForExit();
+ }
+ }
+ else
+ log.Error(Platform.ID + " cannot run games!");
log.Info("Profile " + profile.Name + " process exited.");
}
diff --git a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs
index f30f4f1..708c616 100644
--- a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs
+++ b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs
@@ -127,12 +127,17 @@ namespace AM2RLauncher
// Log distro and version (if it exists)
if (Platform.IsGtk)
{
- string osRelease = File.ReadAllText("/etc/os-release");
- Regex lineRegex = new Regex(".*=.*");
- var results = lineRegex.Matches(osRelease).Cast();
- var version = results.FirstOrDefault(x => x.Value.Contains("VERSION"));
- log.Info("Current Distro: " + results.FirstOrDefault(x => x.Value.Contains("NAME")).Value.Substring(5).Replace("\"", "") +
- (version == null ? "" : " " + version.Value.Substring(8).Replace("\"", "")));
+ if (File.Exists("/etc/os-release"))
+ {
+ string osRelease = File.ReadAllText("/etc/os-release");
+ Regex lineRegex = new Regex(".*=.*");
+ var results = lineRegex.Matches(osRelease).Cast();
+ var version = results.FirstOrDefault(x => x.Value.Contains("VERSION"));
+ log.Info("Current Distro: " + results.FirstOrDefault(x => x.Value.Contains("NAME")).Value.Substring(5).Replace("\"", "") +
+ (version == null ? "" : " " + version.Value.Substring(8).Replace("\"", "")));
+ }
+ else
+ log.Error("Couldn't determine the currently running distro!");
}
// Set the Current Directory to the path the Launcher is located. Fixes some relative path issues.
@@ -162,6 +167,10 @@ namespace AM2RLauncher
Image = am2rIcon
};
+ // Create menubar with defaults for mac
+ if (Platform.IsMac)
+ Menu = new MenuBar { };
+
// Create array from validCount
profileList = new List();
@@ -223,6 +232,9 @@ namespace AM2RLauncher
// Drawable paint event
drawable.Paint += DrawablePaintEvent;
+ // Some systems don't call the paintEvent by default and only do so after actual resizing
+ if (Platform.IsMac)
+ LoadComplete += (sender, e) => { Size = new Size(Size.Width + 1, Size.Height); Size = new Size(Size.Width - 1, Size.Height);};
#region MAIN WINDOW
@@ -309,10 +321,11 @@ namespace AM2RLauncher
// Yes, we know this looks horrific on GTK. Sorry.
// We're not exactly in a position to rewrite the entire DropDown object as a Drawable child, but if you want to, you're more than welcome!
+ // Mac gets a default BackgroundColor because it looks waaaaaaay better.
profileDropDown = new DropDown
{
TextColor = colGreen,
- BackgroundColor = colBGNoAlpha,
+ BackgroundColor = Platform.IsWinForms ? colBGNoAlpha : new Color(),
};
// In order to not have conflicting theming, we just always respect the users theme for dropdown on GTK.
if (Platform.IsGtk)
@@ -518,7 +531,7 @@ namespace AM2RLauncher
languageDropDown = new DropDown
{
TextColor = colGreen,
- BackgroundColor = colBGNoAlpha,
+ BackgroundColor = Platform.IsWinForms ? colBGNoAlpha : new Color(),
};
if (Platform.IsGtk)
languageDropDown = new DropDown { };
@@ -608,7 +621,7 @@ namespace AM2RLauncher
mirrorDropDown = new DropDown
{
TextColor = colGreen,
- BackgroundColor = colBGNoAlpha,
+ BackgroundColor = Platform.IsWinForms ? colBGNoAlpha : new Color(),
};
if (Platform.IsGtk)
mirrorDropDown = new DropDown { };
@@ -679,7 +692,7 @@ namespace AM2RLauncher
settingsProfileDropDown = new DropDown
{
TextColor = colGreen,
- BackgroundColor = colBGNoAlpha,
+ BackgroundColor = Platform.IsWinForms ? colBGNoAlpha : new Color(),
};
// In order to not have conflicting theming, we just always respect the users theme for dropdown on GTK.
@@ -813,6 +826,7 @@ namespace AM2RLauncher
if (Platform.IsGtk)
customEnvVarTextBox.LostFocus += CustomEnvVarTextBoxLostFocus;
+ //TODO: These don't work properly on mac? Maybe on other platforms too?
newsWebView.DocumentLoaded += NewsWebViewDocumentLoaded;
changelogWebView.DocumentLoaded += ChangelogWebViewDocumentLoaded;
diff --git a/AM2RLauncher/AM2RLauncher/XML/LauncherConfigXML.cs b/AM2RLauncher/AM2RLauncher/XML/LauncherConfigXML.cs
index 3e6309c..31d4268 100644
--- a/AM2RLauncher/AM2RLauncher/XML/LauncherConfigXML.cs
+++ b/AM2RLauncher/AM2RLauncher/XML/LauncherConfigXML.cs
@@ -49,6 +49,7 @@ namespace AM2RLauncher.XML
{ get; set; }
/// Indicates whether or not to create debug logs of profile. Used for
[XmlAttribute("ProfileDebugLog")]
+ //TODO: WTF WHY!?
public string ProfileDebugLog
{ get; set; }
/// Indicates the custom environment variable(s) as text. Used for