Create variables for often used folders + more code cleanup

pull/32/head
Miepee 4 years ago
parent 7a4ece9e94
commit 5b2147f7f8

@ -18,7 +18,7 @@ namespace AM2RLauncher
// Auto updating is fun!
/// <summary>The Version that identifies this current release.</summary>
public const string VERSION = Core.Core.VERSION;
public const string VERSION = Core.Core.Version;
/// <summary>The Path of the oldConfig. Only gets used Windows-only</summary>
private static readonly string oldConfigPath = CrossPlatformOperations.CURRENTPATH + "/" + CrossPlatformOperations.LAUNCHERNAME + ".oldCfg";

@ -29,94 +29,6 @@ namespace AM2RLauncher
/// </summary>
private static bool isGitProcessGettingCancelled = false;
/// <summary>
/// After the <see cref="playButton"/> has bee loaded, git pull if a repo has been cloned already.
/// </summary>
private async void PlayButtonLoadComplete(object sender, EventArgs e)
{
LoadProfilesAndAdjustLists();
if (!Profile.IsPatchDataCloned() || !(bool)autoUpdateAM2RCheck.Checked)
return;
SetPlayButtonState(PlayButtonState.Downloading);
progressBar.Visible = true;
progressLabel.Visible = true;
progressBar.Value = 0;
// Try to pull first.
try
{
log.Info("Attempting to pull repository " + currentMirror + "...");
await Task.Run(() => Profile.PullPatchData(TransferProgressHandlerMethod));
// Thank you druid, for this case that should never happen
if (!File.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData/profile.xml"))
{
log.Error("Druid PatchData corruption occurred!");
await Application.Instance.InvokeAsync(() =>
{
MessageBox.Show(this, Text.CorruptPatchData, Text.ErrorWindowTitle, MessageBoxType.Error);
});
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
return;
}
}
catch (UserCancelledException ex)
{
log.Info(ex.Message);
MessageBox.Show(this, Text.CorruptPatchData, Text.ErrorWindowTitle, MessageBoxType.Error);
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
}
catch (LibGit2SharpException ex) // This is for any exceptions from libgit
{
// Libgit2sharp error messages are always in english!
if (ex.Message.ToLower().Contains("failed to send request") || ex.Message.ToLower().Contains("connection with the server was terminated") ||
ex.Message.ToLower().Contains("failed to resolve address"))
{
if (!(bool)autoUpdateAM2RCheck.Checked)
{
log.Error("Internet connection failed while attempting to pull repository" + currentMirror + "!");
MessageBox.Show(this, Text.InternetConnectionDrop, Text.WarningWindowTitle, MessageBoxType.Warning);
}
}
else
{
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
}
}
catch (Exception ex) // This is if somehow any other exception might get thrown as well.
{
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
}
finally
{
progressBar.Visible = false;
progressLabel.Visible = false;
LoadProfilesAndAdjustLists();
}
// Handling for updates - if current version does not match PatchData version, rename folder so that we attempt to install!
// Also, add a non-installable profile for it so people can access the older version or delete it from the mod manager.
if (profileList.Count > 0 && Profile.IsProfileInstalled(profileList[0]))
{
ProfileXML currentXML = Serializer.Deserialize<ProfileXML>(File.ReadAllText(CrossPlatformOperations.CURRENTPATH + "/Profiles/Community Updates (Latest)/profile.xml"));
if (currentXML.Version != profileList[0].Version)
{
log.Info("New game version (" + profileList[0].Version + ") detected! Beginning archival of version " + currentXML.Version + "...");
Profile.ArchiveProfile(currentXML);
profileDropDown.SelectedIndex = 0;
LoadProfilesAndAdjustLists();
}
}
SetPlayButtonState(PlayButtonState.Install);
UpdateStateMachine();
}
#region Misc events
/// <summary>
@ -142,6 +54,10 @@ namespace AM2RLauncher
/// </summary>
private void DrawablePaintEvent(object sender, PaintEventArgs e)
{
// Exit if sender is not a Drawable
Drawable drawable = sender as Drawable;
if (drawable == null) return;
// Get drawing variables
float height = drawable.Height;
float width = drawable.Width;
@ -162,7 +78,7 @@ namespace AM2RLauncher
/// 1) Writes the Width, Height, the check if <see cref="MainForm"/> is currently maximized and the ProfileIndex to the Config<br/>
/// 2) Checks if current <see cref="updateState"/> is <see cref="PlayButtonState.Downloading"/>. If yes, it creates a Warning to the end user.
/// </summary>
private void MainformClosing(object sender, CancelEventArgs e)
private void MainFormClosing(object sender, CancelEventArgs e)
{
log.Info("Attempting to close MainForm!");
@ -218,6 +134,89 @@ namespace AM2RLauncher
#region MAIN TAB
/// <summary>
/// After the <see cref="playButton"/> has been loaded, git pull if a repo has been cloned already.
/// </summary>
private async void PlayButtonLoadComplete(object sender, EventArgs e)
{
//Only pull if Patchdata is cloned and user wants it updated
LoadProfilesAndAdjustLists();
if (!Profile.IsPatchDataCloned() || !(bool)autoUpdateAM2RCheck.Checked)
return;
SetPlayButtonState(PlayButtonState.Downloading);
EnableProgressBarAndLabel();
// Try to pull
try
{
log.Info("Attempting to pull repository " + currentMirror + "...");
await Task.Run(() => Profile.PullPatchData(TransferProgressHandlerMethod));
}
catch (UserCancelledException ex)
{
// TODO: why do we delete patchdata if user cancels pulling?
log.Info(ex.Message);
MessageBox.Show(this, Text.CorruptPatchData, Text.ErrorWindowTitle, MessageBoxType.Error);
HelperMethods.DeleteDirectory(Core.Core.PatchDataPath);
}
// This is for any exceptions from libgit
catch (LibGit2SharpException ex)
{
string errMessage = ex.Message.ToLower();
// Libgit2sharp error messages are always in english!
// If internet connection suddenly dropped or site not reachable
if (errMessage.Contains("failed to send request") || errMessage.Contains("connection with the server was terminated") ||
errMessage.Contains("failed to resolve address"))
{
log.Error("Internet connection failed while attempting to pull repository" + currentMirror + "!");
MessageBox.Show(this, Text.InternetConnectionDrop, Text.WarningWindowTitle, MessageBoxType.Warning);
}
// Error message on protected folders. See this for more info: https://docs.microsoft.com/en-us/microsoft-365/security/defender-endpoint/controlled-folders
else if (errMessage.Contains("access is denied"))
{
// Needs localizable text, logging and message box
// Also, check if this is the right place for it.
throw new NotImplementedException();
}
else
{
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
}
}
// This is if somehow any other exception might get thrown as well.
catch (Exception ex)
{
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
}
// At the end of everything, reset progressBar controls
finally
{
DisableProgressBarAndProgressLabel();
LoadProfilesAndAdjustLists();
}
// Handling for updates - if current version does not match PatchData version, rename folder so that we attempt to install!
// Also, add a non-installable profile for it so people can access the older version or delete it from the mod manager.
if ((profileList.Count > 0) && Profile.IsProfileInstalled(profileList[0]))
{
ProfileXML installedUpdatesProfile = Serializer.Deserialize<ProfileXML>(File.ReadAllText(Core.Core.ProfilesPath + "/Community Updates (Latest)/profile.xml"));
if (installedUpdatesProfile.Version != profileList[0].Version)
{
log.Info("New game version (" + profileList[0].Version + ") detected! Beginning archival of version " + installedUpdatesProfile.Version + "...");
Profile.ArchiveProfile(installedUpdatesProfile);
profileDropDown.SelectedIndex = 0;
LoadProfilesAndAdjustLists();
}
}
SetPlayButtonState(PlayButtonState.Install);
UpdateStateMachine();
}
/// <summary>
/// Does a bunch of stuff, depending on the current state of <see cref="updateState"/>.
/// </summary>
@ -237,37 +236,34 @@ namespace AM2RLauncher
log.Info("Attempting to clone repository " + currentMirror + "...");
bool successful = true;
// Update playButton states
// Update playButton states and progress controls
SetPlayButtonState(PlayButtonState.Downloading);
// Enable progressBar
progressBar.Visible = true;
progressLabel.Visible = true;
progressBar.Value = 0;
EnableProgressBarAndLabel();
// Set up progressBar update method
var c = new CloneOptions
{
OnTransferProgress = TransferProgressHandlerMethod
};
CloneOptions cloneOptions = new CloneOptions { OnTransferProgress = TransferProgressHandlerMethod };
// Everything after this is on a different thread, so the rest of the launcher isn't locked up.
// Try to clone
try
{
if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData"))
// Cleanup invalid PatchData directory if it exists
if (Directory.Exists(Core.Core.PatchDataPath))
{
log.Info("PatchData directory already exists, cleaning up...");
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
HelperMethods.DeleteDirectory(Core.Core.PatchDataPath);
}
await Task.Run(() => Repository.Clone(currentMirror, CrossPlatformOperations.CURRENTPATH + "/PatchData", c));
// Separate thread so launcher doesn't get locked
await Task.Run(() => Repository.Clone(currentMirror, Core.Core.PatchDataPath, cloneOptions));
}
// We deliberately cancelled this, so no error handling
catch (UserCancelledException)
{
// We deliberately cancelled this!
successful = false;
}
catch (LibGit2SharpException ex) // This is for any exceptions from libgit
//TODO: this is currently copy-pasted with the PullPatchData method. put this into a separate method.
// For any exceptions from libgit
catch (LibGit2SharpException ex)
{
// Libgit2sharp error messages are always in english!
if (ex.Message.ToLower().Contains("failed to send request") || ex.Message.ToLower().Contains("connection with the server was terminated") ||
@ -280,18 +276,19 @@ namespace AM2RLauncher
{
log.Error("LibGit2SharpException: " + ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData"))
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
if (Directory.Exists(Core.Core.PatchDataPath))
HelperMethods.DeleteDirectory(Core.Core.PatchDataPath);
}
successful = false;
}
catch (Exception ex) // This is if somehow any other exception might get thrown as well.
// This is if somehow any other exception might get thrown as well.
catch (Exception ex)
{
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + " / PatchData"))
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/PatchData");
HelperMethods.DeleteDirectory(Core.Core.PatchDataPath);
successful = false;
}
@ -300,10 +297,7 @@ namespace AM2RLauncher
currentGitObject = 0;
// Reset progressBar after clone is finished
progressLabel.Visible = false;
progressLabel.Text = "";
progressBar.Visible = false;
progressBar.Value = 0;
DisableProgressBarAndProgressLabel();
// Just need to switch this to anything that isn't an "active" state so SetUpdateState() actually does something
SetPlayButtonState(PlayButtonState.Install);
@ -320,13 +314,14 @@ namespace AM2RLauncher
#region Downloading
case PlayButtonState.Downloading:
var result = MessageBox.Show(this, Text.CloseOnCloningText, Text.WarningWindowTitle, MessageBoxButtons.YesNo, MessageBoxType.Warning, MessageBoxDefaultButton.No);
DialogResult result = MessageBox.Show(this, Text.CloseOnCloningText, Text.WarningWindowTitle, MessageBoxButtons.YesNo,
MessageBoxType.Warning, MessageBoxDefaultButton.No);
if (result != DialogResult.Yes)
return;
log.Info("User cancelled download!");
isGitProcessGettingCancelled = true;
// We don't need to delete any folders here, the cancelled gitClone will do that automatically for us :)
// But we should probably wait a bit before proceeding, since cleanup can take a while
Thread.Sleep(1000);
@ -341,7 +336,6 @@ namespace AM2RLauncher
log.Info("Requesting user input for AM2R_11.zip...");
OpenFileDialog fileFinder = GetSingleZipDialog(Text.Select11FileDialog);
if (fileFinder.ShowDialog(this) != DialogResult.Ok)
{
log.Info("User cancelled the selection.");
@ -349,7 +343,7 @@ namespace AM2RLauncher
}
// Default filename is whitespace
if (String.IsNullOrWhiteSpace(fileFinder.FileName))
if (String.IsNullOrWhiteSpace(fileFinder.FileName))
{
log.Error("User did not supply valid input. Cancelling import.");
return;
@ -359,7 +353,7 @@ namespace AM2RLauncher
if (!File.Exists(fileFinder.FileName))
{
log.Error("Selected AM2R_11.zip file not found! Cancelling import.");
break;
return;
}
IsZipAM2R11ReturnCodes errorCode = Profile.CheckIfZipIsAM2R11(fileFinder.FileName);
@ -371,19 +365,17 @@ namespace AM2RLauncher
}
// We check if it exists first, because someone coughDRUIDcough might've copied it into here while on the showDialog
if (fileFinder.FileName != CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip")
File.Copy(fileFinder.FileName, CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip");
if (fileFinder.FileName != Core.Core.AM2R11File)
File.Copy(fileFinder.FileName, Core.Core.AM2R11File);
log.Info("AM2R_11.zip successfully imported.");
UpdateStateMachine();
break;
#endregion
#region Install
case PlayButtonState.Install:
progressBar.Visible = true;
progressBar.Value = 0;
EnableProgressBar();
SetPlayButtonState(PlayButtonState.Installing);
// Make sure the main interface state machines properly
@ -397,13 +389,12 @@ namespace AM2RLauncher
if (OS.IsUnix && !CrossPlatformOperations.CheckIfXdeltaIsInstalled())
{
MessageBox.Show(this, Text.XdeltaNotFound, Text.WarningWindowTitle, MessageBoxButtons.OK);
SetPlayButtonState(PlayButtonState.Install);
UpdateStateMachine();
log.Error("Xdelta not found. Aborting installing a profile...");
return;
}
var progressIndicator = new Progress<int>(UpdateProgressBar);
Progress<int> progressIndicator = new Progress<int>(UpdateProgressBar);
bool useHqMusic = hqMusicPCCheck.Checked.Value;
await Task.Run(() => Profile.InstallProfile(profileList[profileIndex.Value], useHqMusic, progressIndicator));
// This is just for visuals because the average windows end user will ask why it doesn't go to the end otherwise.
@ -415,8 +406,7 @@ namespace AM2RLauncher
log.Error(ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace);
MessageBox.Show(this, ex.Message + "\n*****Stack Trace*****\n\n" + ex.StackTrace, Text.ErrorWindowTitle, MessageBoxType.Error);
}
progressBar.Visible = false;
progressBar.Value = 0;
DisableProgressBar();
// Just need to switch this to anything that isn't an "active" state so SetUpdateState() actually does something
SetPlayButtonState(PlayButtonState.Play);
@ -476,7 +466,7 @@ namespace AM2RLauncher
// Check for java, exit safely with a warning if not found!
if (!CrossPlatformOperations.IsJavaInstalled())
{
MessageBox.Show(this, Text.JavaNotFound, Text.WarningWindowTitle, MessageBoxButtons.OK);
MessageBox.Show(this, Text.JavaNotFound, Text.WarningWindowTitle, MessageBoxButtons.OK);
SetApkButtonState(ApkButtonState.Create);
UpdateStateMachine();
log.Error("Java not found! Aborting Android APK creation.");
@ -496,25 +486,25 @@ namespace AM2RLauncher
UpdateStateMachine();
if (apkButtonState != ApkButtonState.Create) return;
SetApkButtonState(ApkButtonState.Creating);
UpdateStateMachine();
progressBar.Visible = true;
EnableProgressBar();
bool useHqMusic = hqMusicAndroidCheck.Checked.Value;
var progressIndicator = new Progress<int>(UpdateProgressBar);
Progress<int> progressIndicator = new Progress<int>(UpdateProgressBar);
await Task.Run(() => Profile.CreateAPK(profileList[profileIndex.Value], useHqMusic, progressIndicator));
SetApkButtonState(ApkButtonState.Create);
progressBar.Visible = false;
DisableProgressBar();
UpdateStateMachine();
}
/// <summary>Gets called when user selects a different item from <see cref="profileDropDown"/> and changes <see cref="profileAuthorLabel"/> accordingly.</summary>
private void ProfileDropDownSelectedIndexChanged(object sender, EventArgs e)
{
if (profileDropDown.SelectedIndex == -1 && profileDropDown.Items.Count == 0) return;
if ((profileDropDown.SelectedIndex == -1) && (profileDropDown.Items.Count == 0)) return;
profileIndex = profileDropDown.SelectedIndex;
log.Debug("profileDropDown.SelectedIndex has been changed to " + profileIndex + ".");
@ -522,8 +512,8 @@ namespace AM2RLauncher
profileAuthorLabel.Text = Text.Author + " " + profileList[profileDropDown.SelectedIndex].Author;
profileVersionLabel.Text = Text.VersionLabel + " " + profileList[profileDropDown.SelectedIndex].Version;
if (profileDropDown.SelectedIndex != 0 && (profileList[profileDropDown.SelectedIndex].SaveLocation == "%localappdata%/AM2R" ||
profileList[profileDropDown.SelectedIndex].SaveLocation == "default"))
if ((profileDropDown.SelectedIndex != 0) && ((profileList[profileDropDown.SelectedIndex].SaveLocation == "%localappdata%/AM2R") ||
(profileList[profileDropDown.SelectedIndex].SaveLocation == "default")))
saveWarningLabel.Visible = true;
else
saveWarningLabel.Visible = false;
@ -617,8 +607,9 @@ namespace AM2RLauncher
log.Info("Overwriting mirror in gitconfig.");
// Check if the gitConfig exists, if yes regex the gitURL, and replace it with the new current Mirror.
string gitConfigPath = CrossPlatformOperations.CURRENTPATH + "/PatchData/.git/config";
string gitConfigPath = Core.Core.PatchDataPath + "/.git/config";
if (!File.Exists(gitConfigPath)) return;
string gitConfig = File.ReadAllText(gitConfigPath);
Regex gitURLRegex = new Regex("https://.*\\.git");
Match match = gitURLRegex.Match(gitConfig);
@ -669,7 +660,7 @@ namespace AM2RLauncher
log.Info("Overwriting mirror in gitconfig.");
// Check if the gitConfig exists, if yes regex the gitURL, and replace it with the new current Mirror.
string gitConfigPath = CrossPlatformOperations.CURRENTPATH + "/PatchData/.git/config";
string gitConfigPath = Core.Core.PatchDataPath + "/.git/config";
if (!File.Exists(gitConfigPath)) return;
string gitConfig = File.ReadAllText(gitConfigPath);
Match match = gitURLRegex.Match(gitConfig);
@ -720,9 +711,8 @@ namespace AM2RLauncher
//TODO: move most of this into AM2RLauncher.Profile?
FileInfo modFile = new FileInfo(fileFinder.FileName);
string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName;
string modFileName = Path.GetFileNameWithoutExtension(modFile.Name);
string extractedModDir = modsDir + "/" + modFileName;
string extractedModDir = Core.Core.ModsPath + "/" + modFileName;
// Check first, if the directory is already there, if yes, throw error
if (Directory.Exists(extractedModDir))
@ -805,7 +795,7 @@ namespace AM2RLauncher
updateModButton.ToolTip = HelperMethods.GetText(Text.UpdateModButtonToolTip, profileName);
}
profileButton.Enabled = Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profileName);
profileButton.Enabled = Directory.Exists(Core.Core.ProfilesPath + "/" + profileName);
profileButton.ToolTip = HelperMethods.GetText(Text.OpenProfileFolderToolTip, profileName);
saveButton.Enabled = true;
saveButton.ToolTip = HelperMethods.GetText(Text.OpenSaveFolderToolTip, profileName);
@ -826,7 +816,7 @@ namespace AM2RLauncher
return;
ProfileXML profile = profileList[modSettingsProfileDropDown.SelectedIndex];
log.Info("User opened the profile directory for profile " + profile.Name + ", which is " + profile.SaveLocation);
CrossPlatformOperations.OpenFolder(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name);
CrossPlatformOperations.OpenFolder(Core.Core.ProfilesPath + "/" + profile.Name);
}
/// <summary>
@ -895,9 +885,8 @@ namespace AM2RLauncher
//TODO: move most of this into AM2RLauncher.Profile?
FileInfo modFile = new FileInfo(fileFinder.FileName);
string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName;
string extractedName = Path.GetFileNameWithoutExtension(modFile.Name) + "_new";
string extractedModDir = modsDir + "/" + extractedName;
string extractedModDir = Core.Core.ModsPath + "/" + extractedName;
// If for some reason old files remain, delete them so that extraction doesn't throw
if (Directory.Exists(extractedModDir))
@ -927,7 +916,7 @@ namespace AM2RLauncher
HelperMethods.DeleteDirectory(extractedModDir);
return;
}
// If user doesn't want to update, cleanup
DialogResult updateResult = MessageBox.Show(this, HelperMethods.GetText(Text.UpdateModWarning, currentProfile.Name), Text.WarningWindowTitle,
MessageBoxButtons.OKCancel, MessageBoxType.Warning, MessageBoxDefaultButton.Cancel);
@ -951,7 +940,7 @@ namespace AM2RLauncher
DeleteProfileAndAdjustLists(currentProfile);
// Rename directory to take the old one's place
string originalFolder = modsDir + "/" + Path.GetFileNameWithoutExtension(modFile.Name);
string originalFolder = Core.Core.ModsPath + "/" + Path.GetFileNameWithoutExtension(modFile.Name);
Directory.Move(extractedModDir, originalFolder);
// Adjust our lists so it gets recognized

@ -84,5 +84,31 @@ namespace AM2RLauncher
fileDialog.Filters.Add(new FileFilter(Text.ZipArchiveText, ".zip"));
return fileDialog;
}
private void DisableProgressBar()
{
progressBar.Visible = false;
progressBar.Value = 0;
}
private void EnableProgressBar()
{
progressBar.Visible = true;
progressBar.Value = 0;
}
private void DisableProgressBarAndProgressLabel()
{
DisableProgressBar();
progressLabel.Visible = false;
progressLabel.Text = "";
}
private void EnableProgressBarAndLabel()
{
EnableProgressBar();
progressLabel.Visible = true;
progressLabel.Text = "";
}
}
}

@ -188,7 +188,7 @@ namespace AM2RLauncher
log.Info("Start the launcher with Size: " + ClientSize.Width + ", " + ClientSize.Height);
if (Boolean.Parse(CrossPlatformOperations.ReadFromConfig("IsMaximized"))) Maximize();
drawable = new Drawable { BackgroundColor = colBGNoAlpha };
Drawable drawable = new Drawable { BackgroundColor = colBGNoAlpha };
// Drawable paint event
drawable.Paint += DrawablePaintEvent;
@ -275,7 +275,7 @@ namespace AM2RLauncher
// Profiles dropdown
// Yes, we know this looks horrific on GTK. Sorry.
// 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
@ -354,11 +354,11 @@ namespace AM2RLauncher
// Version number label
Label versionLabel = new Label
Label versionLabel = new Label
{
Text = "v" + VERSION + (isThisRunningFromWine ? "-WINE" : ""),
Width = 48, TextAlignment = TextAlignment.Right, TextColor = colGreen,
Font = new Font(SystemFont.Default, 12)
Font = new Font(SystemFont.Default, 12)
};
// Tie everything together
@ -605,7 +605,7 @@ namespace AM2RLauncher
mirrorDropDown = new DropDown();
mirrorDropDown.Items.AddRange(mirrorDescriptionList); // As above, find a way to get this inside the dropDown definition
mirrorIndex = (Int32.Parse(CrossPlatformOperations.ReadFromConfig("MirrorIndex")) < mirrorDropDown.Items.Count) ? Int32.Parse(CrossPlatformOperations.ReadFromConfig("MirrorIndex"))
mirrorIndex = (Int32.Parse(CrossPlatformOperations.ReadFromConfig("MirrorIndex")) < mirrorDropDown.Items.Count) ? Int32.Parse(CrossPlatformOperations.ReadFromConfig("MirrorIndex"))
: 0;
mirrorDropDown.SelectedIndex = mirrorIndex;
@ -784,7 +784,7 @@ namespace AM2RLauncher
log.Info("All UI objects have been initialized, UI has been set up.");
log.Info("Beginning event linkage...");
Closing += MainformClosing;
Closing += MainFormClosing;
showButton.Click += ShowButtonClick;
profileDropDown.SelectedIndexChanged += ProfileDropDownSelectedIndexChanged;
languageDropDown.SelectedIndexChanged += LanguageDropDownSelectedIndexChanged;
@ -858,10 +858,6 @@ namespace AM2RLauncher
/// <summary><see cref="List{ListItem}"/> of <see cref="ListItem"/> so that Eto's annoying IListItem interface is appeased. Used for mirror name display in DropDowns.</summary>
private List<ListItem> mirrorDescriptionList;
// UI Elements
/// <summary>The main control of the main page, used to draw the <see cref="formBG"/> and hold the main interface.</summary>
private Drawable drawable;
/// <summary>A <see cref="ColorButton"/> that acts as the main Button</summary>
private ColorButton playButton;
/// <summary>A <see cref="ColorButton"/> which is only used for creating APK's</summary>

@ -17,17 +17,37 @@ public static class Core
public static readonly ILog Log = LogManager.GetLogger(typeof(Core));
/// <summary>The Version that identifies this current release.</summary>
public const string VERSION = "2.2.0";
public const string Version = "2.2.0";
/// <summary>
/// Checks if this is run via WINE.
/// Indicates whether or not we have established an internet connection.
/// </summary>
public static readonly bool IsThisRunningFromWine = CheckIfRunFromWINE();
public static readonly bool IsInternetThere = HelperMethods.IsConnectedToInternet();
/// <summary>
/// Indicates whether or not we have established an internet connection.
/// Path where the Launcher's PatchData folder is located.
/// </summary>
public static readonly bool IsInternetThere = HelperMethods.IsConnectedToInternet();
public static readonly string PatchDataPath = CrossPlatformOperations.CURRENTPATH + "/PatchData";
/// <summary>
/// Path where the AM2R_11.zip is located.
/// </summary>
public static readonly string AM2R11File = CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip";
/// <summary>
/// Path where the Launcher's Profiles folder is located.
/// </summary>
public static readonly string ProfilesPath = CrossPlatformOperations.CURRENTPATH + "/Profiles";
/// <summary>
/// Path where the Launcher's Mods folder is located.
/// </summary>
public static readonly string ModsPath = CrossPlatformOperations.CURRENTPATH + "/Mods";
/// <summary>
/// Checks if this is run via WINE.
/// </summary>
public static readonly bool IsThisRunningFromWine = CheckIfRunFromWINE();
/// <summary>
/// Checks if this is ran from WINE
@ -35,9 +55,9 @@ public static class Core
/// <returns><see langword="true"/> if run from WINE, <see langword="false"/> if not.</returns>
private static bool CheckIfRunFromWINE()
{
if (OS.IsWindows && Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\Wine") != null)
if (OS.IsWindows && (Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\Wine") != null))
return true;
return false;
}

@ -17,7 +17,7 @@ public static class CrossPlatformOperations
/// <summary>
/// The logger for <see cref="Core"/>, used to write any caught exceptions.
/// </summary>
private static readonly ILog log = Core.Log;
private static readonly ILog log = LogManager.GetLogger(typeof(CrossPlatformOperations));
/// <summary>
/// Name of the Launcher executable.
@ -410,7 +410,7 @@ public static class CrossPlatformOperations
if (originalOutput == output || !File.Exists(output))
return;
File.Delete(originalOutput);
File.Move(output, originalOutput);
}
@ -458,7 +458,8 @@ public static class CrossPlatformOperations
/// <item><b>$AM2RLAUNCHERDATA</b> environment variable is read and folders are recursively generated.</item>
/// <item>The current OS is checked. For Windows, the path where the executable is located will be returned.<br/>
/// For Linux, <b>$XDG_DATA_HOME/AM2RLauncher</b> will be returned.
/// Should <b>$XDG_DATA_HOME</b> be empty, it will default to <b>$HOME/.local/share</b>.</item>
/// Should <b>$XDG_DATA_HOME</b> be empty, it will default to <b>$HOME/.local/share</b>.<br/>
/// For Mac, <b>HOME/Library/AM2RLauncher"</b> will be returned.</item>
/// <item>The path where the executable is located will be returned.</item>
/// </list>
/// Should any errors occur, it falls down to the next step.

@ -59,7 +59,7 @@ public static class Profile
// If we have a cache, return that instead
if (isAM2R11InstalledCache != null) return isAM2R11InstalledCache.Value;
string am2r11file = CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip";
string am2r11file = Core.AM2R11File;
// Return safely if file doesn't exist
if (!File.Exists(am2r11file)) return false;
lastAM2R11ZipMD5 = HelperMethods.CalculateMD5(am2r11file);
@ -82,15 +82,14 @@ public static class Profile
private static void InvalidateAM2R11InstallCache()
{
// If the file exists, and its hash matches with ours, don't invalidate
if (File.Exists(CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip") &&
HelperMethods.CalculateMD5(CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip") == lastAM2R11ZipMD5)
if ((HelperMethods.CalculateMD5(Core.AM2R11File) == lastAM2R11ZipMD5))
return;
isAM2R11InstalledCache = null;
}
/// <summary>
/// Checks if a Zip file is a valid AM2R_1.1 zip.
/// Checks if a Zip file is a valid AM2R_1.1 zip.
/// </summary>
/// <param name="zipPath">Full Path to the Zip file to check.</param>
/// <returns><see cref="IsZipAM2R11ReturnCodes"/> detailing the result</returns>
@ -152,35 +151,34 @@ public static class Profile
/// </summary>
public static void PullPatchData(Func<TransferProgress, bool> transferProgressHandlerMethod)
{
using (var repo = new Repository(CrossPlatformOperations.CURRENTPATH + "/PatchData"))
{
// Permanently undo commits not pushed to remote
Branch originMaster = repo.Branches.ToList().FirstOrDefault(b => b.FriendlyName.Contains("origin/master") || b.FriendlyName.Contains("origin/main"));
if (originMaster == null)
throw new UserCancelledException("Neither branch 'master' nor branch 'main' could be found! Corrupted or invalid git repo ? Deleting PatchData...");
using Repository repo = new Repository(Core.PatchDataPath);
repo.Reset(ResetMode.Hard, originMaster.Tip);
// Throw if we neither have a master nor main branch
Branch originMaster = repo.Branches.FirstOrDefault(b => b.FriendlyName.Contains("origin/master") || b.FriendlyName.Contains("origin/main"));
if (originMaster == null)
throw new UserCancelledException("Neither branch 'master' nor branch 'main' could be found! Corrupted or invalid git repo?");
// Credential information to fetch
// Permanently undo commits not pushed to remote
repo.Reset(ResetMode.Hard, originMaster.Tip);
PullOptions options = new PullOptions();
options.FetchOptions = new FetchOptions();
options.FetchOptions.OnTransferProgress += tp => transferProgressHandlerMethod(tp);
// Credential information to fetch
PullOptions options = new PullOptions
{
FetchOptions = new FetchOptions { OnTransferProgress = tp => transferProgressHandlerMethod(tp)}
};
// User information to create a merge commit
var signature = new Signature("null", "null", DateTimeOffset.Now);
// Create dummy user information to create a merge commit
Signature signature = new Signature("null", "null", DateTimeOffset.Now);
// Pull
try
{
Commands.Pull(repo, signature, options);
}
catch
{
log.Error("Repository pull attempt failed!");
return;
}
// Pull
try
{
Commands.Pull(repo, signature, options);
}
catch
{
log.Error("Repository pull attempt failed!");
return;
}
log.Info("Repository pulled successfully.");
}
@ -196,19 +194,19 @@ public static class Profile
List<ProfileXML> profileList = new List<ProfileXML>();
// Check for and add the Community Updates profile
if (File.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData/profile.xml"))
if (File.Exists(Core.PatchDataPath + "/profile.xml"))
{
ProfileXML profile = Serializer.Deserialize<ProfileXML>(File.ReadAllText(CrossPlatformOperations.CURRENTPATH + "/PatchData/profile.xml"));
ProfileXML profile = Serializer.Deserialize<ProfileXML>(File.ReadAllText(Core.PatchDataPath + "/profile.xml"));
profile.DataPath = "/PatchData/data";
profileList.Add(profile);
}
// Safety check to generate the Mods folder if it does not exist
if (!Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Mods"))
Directory.CreateDirectory(CrossPlatformOperations.CURRENTPATH + "/Mods");
if (!Directory.Exists(Core.ModsPath))
Directory.CreateDirectory(Core.ModsPath);
// Get Mods folder info
DirectoryInfo modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods");
DirectoryInfo modsDir = new DirectoryInfo(Core.ModsPath);
// Add all extracted profiles in Mods to the profileList.
foreach (DirectoryInfo dir in modsDir.GetDirectories())
@ -254,19 +252,19 @@ public static class Profile
log.Info("Archiving " + profile.Name);
string profileArchivePath = CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name;
string profileArchivePath = Core.ProfilesPath + "/" + profile.Name;
// Do NOT overwrite if a path with this name already exists! It is likely an existing user archive.
if (!Directory.Exists(profileArchivePath))
{
// Rename current profile if we have it installed
if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + originalName))
Directory.Move(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + originalName, profileArchivePath);
if (Directory.Exists(Core.ProfilesPath + "/" + originalName))
Directory.Move(Core.ProfilesPath + "/" + originalName, profileArchivePath);
// Set as non-installable so that it's just treated as a launching reference
profile.Installable = false;
string modArchivePath = CrossPlatformOperations.CURRENTPATH + "/Mods/" + profile.Name;
string modArchivePath = Core.ModsPath + "/" + profile.Name;
// Do NOT overwrite if a path with this name already exists! It is likely an existing user archive.
if (!Directory.Exists(modArchivePath))
@ -284,7 +282,7 @@ public static class Profile
// If our desired rename already exists, it's probably a user archive... so we just delete the original folder and move on with installation of the new version.
else
{
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + originalName);
HelperMethods.DeleteDirectory(Core.ProfilesPath + "/" + originalName);
log.Info("Cancelling archival! User-defined archive in Profiles already exists.");
}
}
@ -310,8 +308,8 @@ public static class Profile
}
// Delete folder in Profiles
if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name))
HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name);
if (Directory.Exists(Core.ProfilesPath + "/" + profile.Name))
HelperMethods.DeleteDirectory(Core.ProfilesPath + "/" + profile.Name);
log.Info("Successfully deleted profile " + profile.Name + ".");
}
@ -326,13 +324,13 @@ public static class Profile
{
log.Info("Installing profile " + profile.Name + "...");
string profilesHomePath = CrossPlatformOperations.CURRENTPATH + "/Profiles";
string profilesHomePath = Core.ProfilesPath;
string profilePath = profilesHomePath + "/" + profile.Name;
// Failsafe for Profiles directory
if (!Directory.Exists(profilesHomePath))
Directory.CreateDirectory(profilesHomePath);
// 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);
@ -363,7 +361,7 @@ public static class Profile
}
// Extract 1.1
ZipFile.ExtractToDirectory(CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip", profilePath);
ZipFile.ExtractToDirectory(Core.AM2R11File, profilePath);
// Extracted 1.1
progress.Report(33);
@ -383,7 +381,7 @@ public static class Profile
{
datawin = "game.unx";
// Use the exe name based on the desktop file in the AppImage, rather than hard coding it.
string desktopContents = File.ReadAllText(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/AM2R.AppDir/AM2R.desktop");
string desktopContents = File.ReadAllText(Core.PatchDataPath + "/data/AM2R.AppDir/AM2R.desktop");
exe = Regex.Match(desktopContents, @"(?<=Exec=).*").Value;
log.Info("According to AppImage desktop file, using \"" + exe + "\" as game name.");
}
@ -448,7 +446,7 @@ public static class Profile
// HQ music
if (!profile.UsesCustomMusic && useHqMusic)
HelperMethods.DirectoryCopy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/HDR_HQ_in-game_music", profilePath);
HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/HDR_HQ_in-game_music", profilePath);
// Linux post-process
@ -463,7 +461,7 @@ public static class Profile
File.Move(file.FullName, file.DirectoryName + "/" + file.Name.ToLower());
// Copy AppImage template to here
HelperMethods.DirectoryCopy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/AM2R.AppDir", profilePath + "/AM2R.AppDir/");
HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/AM2R.AppDir", profilePath + "/AM2R.AppDir/");
// Safety checks, in case the folders don't exist
Directory.CreateDirectory(profilePath + "/AM2R.AppDir/usr/bin/");
@ -482,7 +480,7 @@ public static class Profile
Directory.SetCurrentDirectory(profilePath);
Console.SetError(new StreamWriter(Stream.Null));
Environment.SetEnvironmentVariable("ARCH", "x86_64");
Process.Start(CrossPlatformOperations.CURRENTPATH + "/PatchData/utilities/appimagetool-x86_64.AppImage", "-n AM2R.AppDir")?.WaitForExit();
Process.Start(Core.PatchDataPath + "/utilities/appimagetool-x86_64.AppImage", "-n AM2R.AppDir")?.WaitForExit();
Directory.SetCurrentDirectory(workingDir);
Console.SetError(cliError);
@ -504,9 +502,9 @@ public static class Profile
if (Directory.Exists(profilePath + "/lang/fonts"))
Directory.Delete(profilePath + "/lang/fonts", true);
// Move Frameworks, Info.plist and PkgInfo over
HelperMethods.DirectoryCopy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/Frameworks", profilePath.Replace("Resources", "Frameworks"));
HelperMethods.DirectoryCopy(Core.PatchDataPath + "/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);
File.Copy(Core.PatchDataPath + "/data/PkgInfo", profilePath.Replace("Resources", "") + "/PkgInfo", true);
//Put profilePath back to what it was before
profilePath = profilesHomePath + "/" + profile.Name;
}
@ -529,9 +527,9 @@ public static class Profile
/// <returns><see langword="true"/> if yes, <see langword="false"/> if not.</returns>
public static bool IsProfileInstalled(ProfileXML profile)
{
if (OS.IsWindows) return File.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.exe");
if (OS.IsLinux) return File.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.AppImage");
if (OS.IsMac) return Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name + "/AM2R.app");
if (OS.IsWindows) return File.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.exe");
if (OS.IsLinux) return File.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.AppImage");
if (OS.IsMac) return Directory.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.app");
log.Error(OS.Name + " can't have profiles installed!");
return false;
@ -555,8 +553,8 @@ public static class Profile
log.Info("Creating Android APK for profile " + profile.Name + ".");
// Create working dir after some cleanup
string apktoolPath = CrossPlatformOperations.CURRENTPATH + "/PatchData/utilities/android/apktool.jar",
uberPath = CrossPlatformOperations.CURRENTPATH + "/PatchData/utilities/android/uber-apk-signer.jar",
string apktoolPath = Core.PatchDataPath + "/utilities/android/apktool.jar",
uberPath = Core.PatchDataPath + "/utilities/android/uber-apk-signer.jar",
tempDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/temp").FullName,
dataPath = CrossPlatformOperations.CURRENTPATH + profile.DataPath;
if (Directory.Exists(tempDir))
@ -573,11 +571,11 @@ public static class Profile
// Add datafiles: 1.1, new datafiles, hq music, am2r.ini
string workingDir = tempDir + "/AM2RWrapper/assets";
ZipFile.ExtractToDirectory(CrossPlatformOperations.CURRENTPATH + "/AM2R_11.zip", workingDir);
ZipFile.ExtractToDirectory(Core.AM2R11File, workingDir);
HelperMethods.DirectoryCopy(dataPath + "/files_to_copy", workingDir);
if (useHqMusic)
HelperMethods.DirectoryCopy(CrossPlatformOperations.CURRENTPATH + "/PatchData/data/HDR_HQ_in-game_music", workingDir);
HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/HDR_HQ_in-game_music", workingDir);
// Yes, I'm aware this is dumb. If you've got any better ideas for how to copy a seemingly randomly named .ini from this folder to the APK, please let me know.
foreach (FileInfo file in new DirectoryInfo(dataPath).GetFiles().Where(f => f.Name.EndsWith("ini")))
File.Copy(file.FullName, workingDir + "/" + file.Name);
@ -657,7 +655,7 @@ public static class Profile
StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt");
stream.WriteLine("AM2RLauncher " + Core.VERSION + " log generated at " + date);
stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date);
if (Core.IsThisRunningFromWine)
stream.WriteLine("Using WINE!");
@ -671,7 +669,7 @@ public static class Profile
ProcessStartInfo proc = new ProcessStartInfo();
proc.WorkingDirectory = CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name;
proc.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name;
proc.FileName = proc.WorkingDirectory + "/AM2R.exe";
proc.Arguments = arguments;
@ -726,7 +724,7 @@ public static class Profile
string terminalOutput = null;
startInfo.UseShellExecute = false;
startInfo.WorkingDirectory = CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name;
startInfo.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name;
startInfo.FileName = startInfo.WorkingDirectory + "/AM2R.AppImage";
log.Info("CWD of Profile is " + startInfo.WorkingDirectory);
@ -773,7 +771,7 @@ public static class Profile
StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt");
// Write general info
stream.WriteLine("AM2RLauncher " + Core.VERSION + " log generated at " + date);
stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date);
// Write what was in the terminal
stream.WriteLine(terminalOutput);
@ -802,7 +800,7 @@ public static class Profile
StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt");
stream.WriteLine("AM2RLauncher " + Core.VERSION + " log generated at " + date);
stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date);
stream.Flush();
@ -813,7 +811,7 @@ public static class Profile
ProcessStartInfo proc = new ProcessStartInfo();
proc.WorkingDirectory = CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name;
proc.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name;
proc.FileName = "open";
proc.Arguments = arguments;
@ -835,6 +833,6 @@ public static class Profile
public static bool IsPatchDataCloned()
{
// isValid seems to only check for a .git folder, and there are cases where that exists, but not the profile.xml
return File.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData/profile.xml") && Repository.IsValid(CrossPlatformOperations.CURRENTPATH + "/PatchData");
return File.Exists(Core.PatchDataPath + "/profile.xml") && Repository.IsValid(Core.PatchDataPath);
}
}
Loading…
Cancel
Save