From 1b6d1469f99a1bc339c939fc0d019db56dae631b Mon Sep 17 00:00:00 2001 From: Miepee <38186597+Miepee@users.noreply.github.com> Date: Fri, 18 Feb 2022 13:33:52 +0100 Subject: [PATCH] more reorga - add some #regions - rename some methods to be more clearer - cleanup add and delete profile --- .../AM2RLauncher/MainForm/MainForm.Events.cs | 807 +++++++++--------- .../AM2RLauncher/MainForm/MainForm.UI.cs | 6 +- AM2RLauncher/AM2RLauncherCore/Profile.cs | 128 ++- 3 files changed, 465 insertions(+), 476 deletions(-) diff --git a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs index 0b6fb79..fb2b4e8 100644 --- a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs +++ b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.Events.cs @@ -117,6 +117,107 @@ namespace AM2RLauncher UpdateStateMachine(); } + #region Misc events + + /// + /// Fires when the profile layout completes loading. This makes sure that if has nothing in it "on boot", + /// that everything is disabled. + /// + private void ProfileLayoutLoadComplete(object sender, EventArgs e) + { + // Safety check + if ((modSettingsProfileDropDown == null) || (modSettingsProfileDropDown.Items.Count != 0)) return; + addModButton.Enabled = false; + settingsProfileLabel.TextColor = colInactive; + modSettingsProfileDropDown.Enabled = false; + profileButton.Enabled = false; + saveButton.Enabled = false; + updateModButton.Enabled = false; + deleteModButton.Enabled = false; + profileNotesTextArea.TextColor = colInactive; + } + + /// + /// The calls this when you're resizing, in order to resize and scale the application accordingly. + /// + private void DrawablePaintEvent(object sender, PaintEventArgs e) + { + // Get drawing variables + float height = drawable.Height; + float width = drawable.Width; + //TODO: apparently winforms is the big outlier here. Works normal on wpf, I have *no* idea why, seems related to our image. issue has been submitted at eto + float scaleDivisor = OS.IsWindows ? formBG.Width : formBG.Height; + + float scale = height / scaleDivisor; + + // Do the actual scaling + e.Graphics.ScaleTransform(scale); + + // Draw the image, change x offset with some absurd wizardry written at 5 AM + e.Graphics.DrawImage(formBG, ((width / 2) - (height / 1.4745f)) / scale, 0); + } + + /// + /// Gets called when user tries to close . This does a few things:
+ /// 1) Writes the Width, Height, the check if is currently maximized and the ProfileIndex to the Config
+ /// 2) Checks if current is . If yes, it creates a Warning to the end user. + ///
+ private void MainformClosing(object sender, CancelEventArgs e) + { + log.Info("Attempting to close MainForm!"); + + CrossPlatformOperations.WriteToConfig("Width", ClientSize.Width); + CrossPlatformOperations.WriteToConfig("Height", ClientSize.Height); + CrossPlatformOperations.WriteToConfig("IsMaximized", this.WindowState == WindowState.Maximized); + CrossPlatformOperations.WriteToConfig("ProfileIndex", profileIndex.ToString()); + + switch (updateState) + { + // If we're currently still downloading, ask first if user really wants to close and cancel the event if necessary + case UpdateState.Downloading: + { + var result = MessageBox.Show(this, Text.CloseOnCloningText, Text.WarningWindowTitle, MessageBoxButtons.YesNo, + MessageBoxType.Warning, MessageBoxDefaultButton.No); + + if (result == DialogResult.No) + e.Cancel = true; + else + isGitProcessGettingCancelled = true; + // We don't need to delete any folders here, the cancelled gitClone will do that automatically for us :) + break; + } + // We can't close during installing, so we cancel the event. + case UpdateState.Installing: + { + MessageBox.Show(this, Text.CloseOnInstallingText, Text.WarningWindowTitle, MessageBoxButtons.OK, MessageBoxType.Warning); + e.Cancel = true; + break; + } + } + + // This needs to be made invisible, otherwise a tray indicator will be visible (on linux?) that clicking crashes the application + //TODO: this sounds like an eto bug. check if this can get reproduced. + trayIndicator.Visible = false; + + if (e.Cancel) + log.Info("Cancelled MainForm closing event during UpdateState." + updateState + "."); + else + log.Info("Successfully closed MainForm. Exiting main thread."); + } + + /// Gets called when gets clicked and shows the and brings it to the front again. + private void ShowButtonClick(object sender, EventArgs e) + { + log.Info("User has opened the launcher from system tray."); + + this.Show(); + this.BringToFront(); + } + + #endregion + + #region MAIN TAB + /// /// Does a bunch of stuff, depending on the current state of . /// @@ -411,6 +512,28 @@ namespace AM2RLauncher } } + /// Gets called when user selects a different item from and changes accordingly. + private void ProfileDropDownSelectedIndexChanged(object sender, EventArgs e) + { + if (profileDropDown.SelectedIndex == -1 && profileDropDown.Items.Count == 0) return; + + profileIndex = profileDropDown.SelectedIndex; + log.Debug("profileDropDown.SelectedIndex has been changed to " + profileIndex + "."); + + 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")) + saveWarningLabel.Visible = true; + else + saveWarningLabel.Visible = false; + + UpdateStateMachine(); + } + + #endregion + /// /// If no internet access is available, this changes the content of to an empty page only displaying . /// @@ -432,376 +555,309 @@ namespace AM2RLauncher }; } - /// - /// Runs when is clicked. Brings up a file select to select a mod, and adds that to the mod directory. - /// - private void AddModButtonClicked(object sender, EventArgs e) + #region SETTINGS + + /// Gets called when user selects a different item from and writes that to the config. + private void LanguageDropDownSelectedIndexChanged(object sender, EventArgs e) { - log.Info("User requested to add mod. Requesting user input for new mod .zip..."); + log.Info("languageDropDown.SelectedIndex has been changed to " + languageDropDown.SelectedIndex + "."); + CrossPlatformOperations.WriteToConfig("Language", languageDropDown.SelectedIndex == 0 ? "Default" : languageDropDown.Items[languageDropDown.SelectedIndex].Text); + } - OpenFileDialog fileFinder = GetSingleZipDialog(Text.SelectModFileDialog); + /// Gets called when gets clicked and writes its new value to the config. + private void AutoUpdateAM2RCheckChanged(object sender, EventArgs e) + { + log.Info("Auto Update AM2R has been set to " + autoUpdateAM2RCheck.Checked + "."); + CrossPlatformOperations.WriteToConfig("AutoUpdateAM2R", (bool)autoUpdateAM2RCheck.Checked); + } - if (fileFinder.ShowDialog(this) != DialogResult.Ok) - { - log.Info("User cancelled the Mod selection."); - return; - } + /// Gets called when gets clicked and writes its new value to the config. + private void AutoUpdateLauncherCheckChanged(object sender, EventArgs e) + { + log.Info("Auto Update Launcher has been set to " + autoUpdateAM2RCheck.Checked + "."); + CrossPlatformOperations.WriteToConfig("AutoUpdateLauncher", (bool)autoUpdateAM2RCheck.Checked); + } - if (String.IsNullOrWhiteSpace(fileFinder.FileName)) - { - log.Error("User did not supply valid input. Cancelling import."); - LoadProfilesAndAdjustLists(); - return; - } + /// Gets called when gets clicked and writes its new value to the config. + private void HqMusicPCCheckChanged(object sender, EventArgs e) + { + log.Info("PC HQ Music option has been changed to " + hqMusicPCCheck.Checked); + CrossPlatformOperations.WriteToConfig("MusicHQPC", hqMusicPCCheck.Checked); + } - log.Info("User selected \"" + fileFinder.FileName + "\""); + /// Gets called when gets clicked and writes its new value to the config. + private void HqMusicAndroidCheckChanged(object sender, EventArgs e) + { + log.Info("Android HQ Music option has been changed to " + hqMusicAndroidCheck.Checked); + CrossPlatformOperations.WriteToConfig("MusicHQAndroid", hqMusicAndroidCheck.Checked); + } - // If either a directory was selected or the file somehow went missing, cancel - if (!File.Exists(fileFinder.FileName)) - { - log.Error("Selected mod .zip file not found! Cancelling import."); - return; - } + /// + /// Gets called when gets clicked, and writes it's new value to the config. + /// + private void ProfileDebugLogCheckedChanged(object sender, EventArgs e) + { + log.Info("Create Game Debug Logs option has been set to " + profileDebugLogCheck.Checked + "."); + CrossPlatformOperations.WriteToConfig("ProfileDebugLog", profileDebugLogCheck.Checked); + } - FileInfo modFile = new FileInfo(fileFinder.FileName); + /// Gets called when user selects a different item from . + /// It then writes that to the config, and if is not + /// it also overwrites the upstream URL in .git/config. + private void MirrorDropDownSelectedIndexChanged(object sender, EventArgs e) + { + currentMirror = mirrorList[mirrorDropDown.SelectedIndex]; - string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName; - string extractedName = modFile.Name.Replace(".zip", ""); + log.Info("Current mirror has been set to " + currentMirror + "."); - // Extract it and see if it contains a profile.xml. If not, this is invalid + CrossPlatformOperations.WriteToConfig("MirrorIndex", mirrorDropDown.SelectedIndex); - // Check first, if the directory is already there, if yes, throw a message - if (Directory.Exists(modsDir + "/" + extractedName)) - { - ProfileXML profile2 = Serializer.Deserialize(File.ReadAllText(modsDir + "/" + extractedName + "/profile.xml")); - log.Error("Mod is already imported as " + extractedName + "! Cancelling mod import."); + // Don't overwrite the git config while we download!!! + if (updateState == UpdateState.Downloading) return; - MessageBox.Show(this, HelperMethods.GetText(Text.ModIsAlreadyInstalledMessage, profile2.Name), Text.WarningWindowTitle, MessageBoxType.Warning); - return; - } - // Directory doesn't exist -> extract! - ZipFile.ExtractToDirectory(fileFinder.FileName, modsDir + "/" + extractedName); - log.Info("Imported and extracted mod .zip as " + extractedName); + log.Info("Overwriting mirror in gitconfig."); - // Let's check if profile.xml exists in there! If it doesn't throw an error and cleanup - if (!File.Exists(modsDir + "/" + extractedName + "/profile.xml")) - { - log.Error(fileFinder.FileName + " does not contain profile.xml! Cancelling mod import."); + // 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"; + if (!File.Exists(gitConfigPath)) return; + string gitConfig = File.ReadAllText(gitConfigPath); + Regex gitURLRegex = new Regex("https://.*\\.git"); + Match match = gitURLRegex.Match(gitConfig); + gitConfig = gitConfig.Replace(match.Value, currentMirror); + File.WriteAllText(gitConfigPath, gitConfig); + } - MessageBox.Show(this, HelperMethods.GetText(Text.ModIsInvalidMessage, extractedName), Text.ErrorWindowTitle, MessageBoxType.Error); - Directory.Delete(modsDir + "/" + extractedName, true); - File.Delete(CrossPlatformOperations.CURRENTPATH + "/Mods/" + modFile.Name); - return; - } + /// Gets called when gets clicked, displays a warning + /// and enables accordingly. + private void CustomMirrorCheckChanged(object sender, EventArgs e) + { + log.Info("Use Custom Mirror option has been set to " + customMirrorCheck.Checked + "."); + CrossPlatformOperations.WriteToConfig("CustomMirrorEnabled", (bool)customMirrorCheck.Checked); - ProfileXML profile = Serializer.Deserialize(File.ReadAllText(modsDir + "/" + extractedName + "/profile.xml")); + bool enabled = (bool)customMirrorCheck.Checked; + customMirrorTextBox.Enabled = enabled; + mirrorDropDown.Enabled = !enabled; + // Not sure why the dropdown menu needs this hack, but the textBox does not. + if (OS.IsWindows) + mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive; + mirrorLabel.TextColor = !enabled ? colGreen : colInactive; - // Check if the OS versions match - if (OS.Name != profile.OperatingSystem) + // Create warning dialog when enabling + if (enabled) { - log.Error("Mod is for " + profile.OperatingSystem + " while current OS is " + OS.Name + ". Cancelling mod import."); - - MessageBox.Show(this, HelperMethods.GetText(Text.ModIsForWrongOS, profile.Name).Replace("$OS", profile.OperatingSystem).Replace("$CURRENTOS", OS.Name), - Text.ErrorWindowTitle, MessageBoxType.Error); - HelperMethods.DeleteDirectory(modsDir + "/" + extractedName); - return; + MessageBox.Show(this, Text.WarningWindowText, Text.WarningWindowTitle, MessageBoxType.Warning); + currentMirror = customMirrorTextBox.Text; } - - // Check by *name*, if the mod was installed already - if (profileList.FirstOrDefault(p => p.Name == profile.Name) != null || Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name)) + else { - log.Error(profile.Name + " is already installed."); - MessageBox.Show(this, HelperMethods.GetText(Text.ModIsAlreadyInstalledMessage, profile.Name), Text.WarningWindowTitle, MessageBoxType.Warning); - HelperMethods.DeleteDirectory(modsDir + "/" + extractedName); - return; + // Revert mirror to selected index in mirror dropdown + currentMirror = mirrorList[mirrorDropDown.SelectedIndex]; } - - log.Info(profile.Name + " successfully installed."); - MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, profile.Name), Text.SuccessWindowTitle); - - LoadProfilesAndAdjustLists(); - // Adjust profileIndex to point to newly added mod. if its not found for whatever reason, we default to first community updates - modSettingsProfileDropDown.SelectedIndex = profileList.FindIndex(p => p.Name == profile.Name); - if (modSettingsProfileDropDown.SelectedIndex == -1) - modSettingsProfileDropDown.SelectedIndex = 0; } - /// - /// This opens the game files directory for the current profile. - /// - private void ProfilesButtonClickEvent(object sender, EventArgs e) + //TODO: why exactly do we need this? + /// Gets called when gets loaded. + /// Enables and changes colors for and accordingly. + private void CustomMirrorCheckLoadComplete(object sender, EventArgs e) { - if (!IsProfileIndexValid()) - return; - log.Info("User opened the profile directory for profile " + profileList[modSettingsProfileDropDown.SelectedIndex].Name + - ", which is " + profileList[modSettingsProfileDropDown.SelectedIndex].SaveLocation); - CrossPlatformOperations.OpenFolder(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profileList[modSettingsProfileDropDown.SelectedIndex].Name); + bool enabled = (bool)customMirrorCheck.Checked; + customMirrorTextBox.Enabled = enabled; + mirrorDropDown.Enabled = !enabled; + if (OS.IsWindows) + mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive; } /// - /// This opens the save directory for the current profile. + /// If the has lost focus, we set its text as the new . /// - private void SaveButtonClickEvent(object sender, EventArgs e) + private void CustomMirrorTextBoxLostFocus(object sender, EventArgs e) { - if (!IsProfileIndexValid()) - return; - log.Info("User opened the save directory for profile " + profileList[modSettingsProfileDropDown.SelectedIndex].Name + ", which is " + profileList[modSettingsProfileDropDown.SelectedIndex].SaveLocation); - CrossPlatformOperations.OpenFolder(profileList[modSettingsProfileDropDown.SelectedIndex].SaveLocation); - } - - /// - /// Enabled / disables and accordingly. - /// - private void SettingsProfileDropDownSelectedIndexChanged(object sender, EventArgs e) - { - if (modSettingsProfileDropDown.SelectedIndex == -1 && modSettingsProfileDropDown.Items.Count == 0) return; - - string profileName = modSettingsProfileDropDown.Items[modSettingsProfileDropDown.SelectedIndex].Text; - - log.Info("SettingsProfileDropDown.SelectedIndex has been changed to " + modSettingsProfileDropDown.SelectedIndex + "."); - if (modSettingsProfileDropDown.SelectedIndex <= 0 || modSettingsProfileDropDown.Items.Count == 0) - { - deleteModButton.Enabled = false; - deleteModButton.ToolTip = null; - updateModButton.Enabled = false; - updateModButton.ToolTip = null; - profileNotesTextArea.TextColor = colInactive; - } - else + // Check first, if the text is a valid git repo + Regex gitURLRegex = new Regex("https://.*\\.git"); + string mirrorText = customMirrorTextBox.Text; + if (!gitURLRegex.IsMatch(mirrorText)) { - deleteModButton.Enabled = true; - deleteModButton.ToolTip = HelperMethods.GetText(Text.DeleteModButtonToolTip, profileName); - // On non-installable profiles we want to disable updating - updateModButton.Enabled = profileList[modSettingsProfileDropDown.SelectedIndex].Installable; - updateModButton.ToolTip = HelperMethods.GetText(Text.UpdateModButtonToolTip, profileName); + log.Info("User used " + mirrorText + " as a custom Mirror, didn't pass git validation test."); + MessageBox.Show(this, HelperMethods.GetText(Text.InvalidGitURL, mirrorText), Text.ErrorWindowTitle, MessageBoxType.Error); + return; } - profileButton.Enabled = Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profileName); - profileButton.ToolTip = HelperMethods.GetText(Text.OpenProfileFolderToolTip, profileName); - saveButton.Enabled = true; - saveButton.ToolTip = HelperMethods.GetText(Text.OpenSaveFolderToolTip, profileName); + currentMirror = mirrorText; + CrossPlatformOperations.WriteToConfig("CustomMirrorText", currentMirror); - if (modSettingsProfileDropDown.SelectedIndex < 0 || modSettingsProfileDropDown.Items.Count == 0) - return; - profileNotesTextArea.TextColor = colGreen; - profileNotesTextArea.Text = Text.ProfileNotes + "\n" + profileList[modSettingsProfileDropDown.SelectedIndex].ProfileNotes; + 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"; + if (!File.Exists(gitConfigPath)) return; + string gitConfig = File.ReadAllText(gitConfigPath); + Match match = gitURLRegex.Match(gitConfig); + gitConfig = gitConfig.Replace(match.Value, currentMirror); + File.WriteAllText(gitConfigPath, gitConfig); + log.Info("Custom Mirror has been set to " + currentMirror + "."); } /// - /// Fires when the profile layout completes loading. This makes sure that if has nothing in it "on boot", - /// that everything is disabled. + /// If has lost focus, we write its text to the config. /// - private void ProfileLayoutLoadComplete(object sender, EventArgs e) + private void CustomEnvVarTextBoxLostFocus(object sender, EventArgs e) { - // Safety check - if ((modSettingsProfileDropDown == null) || (modSettingsProfileDropDown.Items.Count != 0)) return; - addModButton.Enabled = false; - settingsProfileLabel.TextColor = colInactive; - modSettingsProfileDropDown.Enabled = false; - profileButton.Enabled = false; - saveButton.Enabled = false; - updateModButton.Enabled = false; - deleteModButton.Enabled = false; - profileNotesTextArea.TextColor = colInactive; + log.Info("Custom Environment variables have been set to \"" + customEnvVarTextBox.Text + "\"."); + CrossPlatformOperations.WriteToConfig("CustomEnvVar", customEnvVarTextBox.Text); } + #endregion + + #region MOD SETTINGS + /// - /// The calls this when you're resizing, in order to resize and scale the application accordingly. + /// Runs when is clicked. Brings up a file select to select a mod, and adds that to the mod directory. /// - private void DrawablePaintEvent(object sender, PaintEventArgs e) + private void AddModButtonClicked(object sender, EventArgs e) { - // Get drawing variables - float height = drawable.Height; - float width = drawable.Width; - //TODO: apparently winforms is the big outlier here. Works normal on wpf, I have *no* idea why, seems related to our image. issue has been submitted at eto - float scaleDivisor = OS.IsWindows ? formBG.Width : formBG.Height; - - float scale = height / scaleDivisor; + log.Info("User requested to add mod. Requesting user input for new mod .zip..."); - // Do the actual scaling - e.Graphics.ScaleTransform(scale); + OpenFileDialog fileFinder = GetSingleZipDialog(Text.SelectModFileDialog); - // Draw the image, change x offset with some absurd wizardry written at 5 AM - e.Graphics.DrawImage(formBG, ((width / 2) - (height / 1.4745f)) / scale, 0); - } + // If user didn't press ok, cancel + if (fileFinder.ShowDialog(this) != DialogResult.Ok) + { + log.Info("User cancelled the Mod selection."); + return; + } - /// Gets called when gets clicked and shows the and brings it to the front again. - private void ShowButtonClick(object sender, EventArgs e) - { - log.Info("User has opened the launcher from system tray."); + log.Info("User selected \"" + fileFinder.FileName + "\""); - this.Show(); - this.BringToFront(); - } + // If either a directory was selected, user pressed OK without selecting anything or the file somehow went missing, cancel + if (!File.Exists(fileFinder.FileName)) + { + log.Error("Selected mod .zip file not found! Cancelling import."); + return; + } - /// Gets called when gets clicked and writes its new value to the config. - private void HqMusicPCCheckChanged(object sender, EventArgs e) - { - log.Info("PC HQ Music option has been changed to " + hqMusicPCCheck.Checked); - CrossPlatformOperations.WriteToConfig("MusicHQPC", hqMusicPCCheck.Checked); - } + //TODO: move most of this into AM2RLauncher.Profile? - /// Gets called when gets clicked and writes its new value to the config. - private void HqMusicAndroidCheckChanged(object sender, EventArgs e) - { - log.Info("Android HQ Music option has been changed to " + hqMusicAndroidCheck.Checked); - CrossPlatformOperations.WriteToConfig("MusicHQAndroid", hqMusicAndroidCheck.Checked); - } + FileInfo modFile = new FileInfo(fileFinder.FileName); + string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName; + string modFileName = Path.GetFileNameWithoutExtension(modFile.Name); + string extractedModDir = modsDir + "/" + modFileName; - /// Gets called when user selects a different item from and changes accordingly. - private void ProfileDropDownSelectedIndexChanged(object sender, EventArgs e) - { - if (profileDropDown.SelectedIndex == -1 && profileDropDown.Items.Count == 0) return; + // Check first, if the directory is already there, if yes, throw error + if (Directory.Exists(extractedModDir)) + { + string existingProfileName = Serializer.Deserialize(File.ReadAllText(extractedModDir + "/profile.xml")).Name; + log.Error("Mod is already imported as " + modFileName + "! Cancelling mod import."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModIsAlreadyInstalledMessage, existingProfileName), Text.WarningWindowTitle, MessageBoxType.Warning); + return; + } - profileIndex = profileDropDown.SelectedIndex; - log.Debug("profileDropDown.SelectedIndex has been changed to " + profileIndex + "."); + // Directory doesn't exist -> extract! + ZipFile.ExtractToDirectory(modFile.FullName, extractedModDir); + log.Info("Imported and extracted mod .zip as " + modFileName); - profileAuthorLabel.Text = Text.Author + " " + profileList[profileDropDown.SelectedIndex].Author; - profileVersionLabel.Text = Text.VersionLabel + " " + profileList[profileDropDown.SelectedIndex].Version; + // If profile.xml doesn't exist, throw an error and cleanup + if (!File.Exists(extractedModDir + "/profile.xml")) + { + log.Error(modFile.Name + " does not contain profile.xml! Cancelling mod import."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModIsInvalidMessage, modFileName), Text.ErrorWindowTitle, MessageBoxType.Error); + Directory.Delete(extractedModDir, true); + return; + } - if (profileDropDown.SelectedIndex != 0 && (profileList[profileDropDown.SelectedIndex].SaveLocation == "%localappdata%/AM2R" || - profileList[profileDropDown.SelectedIndex].SaveLocation == "default")) - saveWarningLabel.Visible = true; - else - saveWarningLabel.Visible = false; + ProfileXML profile = Serializer.Deserialize(File.ReadAllText(extractedModDir + "/profile.xml")); - UpdateStateMachine(); - } + // If OS versions mismatch, throw error and cleanup + if (OS.Name != profile.OperatingSystem) + { + log.Error("Mod is for " + profile.OperatingSystem + " while current OS is " + OS.Name + ". Cancelling mod import."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModIsForWrongOS, profile.Name).Replace("$OS", profile.OperatingSystem).Replace("$CURRENTOS", OS.Name), + Text.ErrorWindowTitle, MessageBoxType.Error); + HelperMethods.DeleteDirectory(extractedModDir); + return; + } - /// Gets called when user selects a different item from and writes that to the config. - private void LanguageDropDownSelectedIndexChanged(object sender, EventArgs e) - { - log.Info("languageDropDown.SelectedIndex has been changed to " + languageDropDown.SelectedIndex + "."); - CrossPlatformOperations.WriteToConfig("Language", languageDropDown.SelectedIndex == 0 ? "Default" : languageDropDown.Items[languageDropDown.SelectedIndex].Text); - } + // If mod was installed/added by *name* already, throw error and cleanup + if (profileList.FirstOrDefault(p => p.Name == profile.Name) != null) + { + log.Error(profile.Name + " is already installed."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModIsAlreadyInstalledMessage, profile.Name), Text.WarningWindowTitle, MessageBoxType.Warning); + HelperMethods.DeleteDirectory(extractedModDir); + return; + } - /// Gets called when gets clicked and writes its new value to the config. - private void AutoUpdateAM2RCheckChanged(object sender, EventArgs e) - { - log.Info("Auto Update AM2R has been set to " + autoUpdateAM2RCheck.Checked + "."); - CrossPlatformOperations.WriteToConfig("AutoUpdateAM2R", (bool)autoUpdateAM2RCheck.Checked); - } + // Reload list so mod gets recognized + LoadProfilesAndAdjustLists(); + // Adjust profileIndex to point to newly added mod. if its not found for whatever reason, we default to first community updates + modSettingsProfileDropDown.SelectedIndex = profileList.FindIndex(p => p.Name == profile.Name); + if (modSettingsProfileDropDown.SelectedIndex == -1) + modSettingsProfileDropDown.SelectedIndex = 0; - /// Gets called when gets clicked and writes its new value to the config. - private void AutoUpdateLauncherCheckChanged(object sender, EventArgs e) - { - log.Info("Auto Update Launcher has been set to " + autoUpdateAM2RCheck.Checked + "."); - CrossPlatformOperations.WriteToConfig("AutoUpdateLauncher", (bool)autoUpdateAM2RCheck.Checked); + log.Info(profile.Name + " successfully added."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, profile.Name), Text.SuccessWindowTitle); } - /// Gets called when gets clicked, displays a warning - /// and enables accordingly. - private void CustomMirrorCheckChanged(object sender, EventArgs e) + /// + /// Enabled / disables and accordingly. + /// + private void ModSettingsProfileDropDownSelectedIndexChanged(object sender, EventArgs e) { - log.Info("Use Custom Mirror option has been set to " + customMirrorCheck.Checked + "."); - CrossPlatformOperations.WriteToConfig("CustomMirrorEnabled", (bool)customMirrorCheck.Checked); + if (modSettingsProfileDropDown.SelectedIndex == -1 && modSettingsProfileDropDown.Items.Count == 0) return; - bool enabled = (bool)customMirrorCheck.Checked; - customMirrorTextBox.Enabled = enabled; - mirrorDropDown.Enabled = !enabled; - // Not sure why the dropdown menu needs this hack, but the textBox does not. - if (OS.IsWindows) - mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive; - mirrorLabel.TextColor = !enabled ? colGreen : colInactive; + string profileName = modSettingsProfileDropDown.Items[modSettingsProfileDropDown.SelectedIndex].Text; - // Create warning dialog when enabling - if (enabled) + log.Info("SettingsProfileDropDown.SelectedIndex has been changed to " + modSettingsProfileDropDown.SelectedIndex + "."); + if (modSettingsProfileDropDown.SelectedIndex <= 0 || modSettingsProfileDropDown.Items.Count == 0) { - MessageBox.Show(this, Text.WarningWindowText, Text.WarningWindowTitle, MessageBoxType.Warning); - currentMirror = customMirrorTextBox.Text; + deleteModButton.Enabled = false; + deleteModButton.ToolTip = null; + updateModButton.Enabled = false; + updateModButton.ToolTip = null; + profileNotesTextArea.TextColor = colInactive; } else { - // Revert mirror to selected index in mirror dropdown - currentMirror = mirrorList[mirrorDropDown.SelectedIndex]; + deleteModButton.Enabled = true; + deleteModButton.ToolTip = HelperMethods.GetText(Text.DeleteModButtonToolTip, profileName); + // On non-installable profiles we want to disable updating + updateModButton.Enabled = profileList[modSettingsProfileDropDown.SelectedIndex].Installable; + updateModButton.ToolTip = HelperMethods.GetText(Text.UpdateModButtonToolTip, profileName); } - } - - /// Gets called when user selects a different item from . - /// It then writes that to the config, and if is not - /// it also overwrites the upstream URL in .git/config. - private void MirrorDropDownSelectedIndexChanged(object sender, EventArgs e) - { - currentMirror = mirrorList[mirrorDropDown.SelectedIndex]; - - log.Info("Current mirror has been set to " + currentMirror + "."); - - CrossPlatformOperations.WriteToConfig("MirrorIndex", mirrorDropDown.SelectedIndex); - // Don't overwrite the git config while we download!!! - if (updateState == UpdateState.Downloading) return; - - log.Info("Overwriting mirror in gitconfig."); + profileButton.Enabled = Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profileName); + profileButton.ToolTip = HelperMethods.GetText(Text.OpenProfileFolderToolTip, profileName); + saveButton.Enabled = true; + saveButton.ToolTip = HelperMethods.GetText(Text.OpenSaveFolderToolTip, profileName); - // 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"; - if (!File.Exists(gitConfigPath)) return; - string gitConfig = File.ReadAllText(gitConfigPath); - Regex gitURLRegex = new Regex("https://.*\\.git"); - Match match = gitURLRegex.Match(gitConfig); - gitConfig = gitConfig.Replace(match.Value, currentMirror); - File.WriteAllText(gitConfigPath, gitConfig); - } + if (modSettingsProfileDropDown.SelectedIndex < 0 || modSettingsProfileDropDown.Items.Count == 0) + return; + profileNotesTextArea.TextColor = colGreen; + profileNotesTextArea.Text = Text.ProfileNotes + "\n" + profileList[modSettingsProfileDropDown.SelectedIndex].ProfileNotes; - /// - /// Gets called when gets clicked, and writes it's new value to the config. - /// - private void ProfileDebugLogCheckedChanged(object sender, EventArgs e) - { - log.Info("Create Game Debug Logs option has been set to " + profileDebugLogCheck.Checked + "."); - CrossPlatformOperations.WriteToConfig("ProfileDebugLog", profileDebugLogCheck.Checked); } /// - /// If the has lost focus, we set its text as the new . + /// This opens the game files directory for the current profile. /// - private void CustomMirrorTextBoxLostFocus(object sender, EventArgs e) + private void ProfileDataButtonClickEvent(object sender, EventArgs e) { - // Check first, if the text is a valid git repo - Regex gitURLRegex = new Regex("https://.*\\.git"); - string mirrorText = customMirrorTextBox.Text; - if (!gitURLRegex.IsMatch(mirrorText)) - { - log.Info("User used " + mirrorText + " as a custom Mirror, didn't pass git validation test."); - MessageBox.Show(this, HelperMethods.GetText(Text.InvalidGitURL, mirrorText), Text.ErrorWindowTitle, MessageBoxType.Error); + if (!IsProfileIndexValid()) return; - } - - currentMirror = mirrorText; - CrossPlatformOperations.WriteToConfig("CustomMirrorText", currentMirror); - - 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"; - if (!File.Exists(gitConfigPath)) return; - string gitConfig = File.ReadAllText(gitConfigPath); - Match match = gitURLRegex.Match(gitConfig); - gitConfig = gitConfig.Replace(match.Value, currentMirror); - File.WriteAllText(gitConfigPath, gitConfig); - - log.Info("Custom Mirror has been set to " + currentMirror + "."); + 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); } /// - /// If has lost focus, we write its text to the config. + /// This opens the save directory for the current profile. /// - private void CustomEnvVarTextBoxLostFocus(object sender, EventArgs e) - { - log.Info("Custom Environment variables have been set to \"" + customEnvVarTextBox.Text + "\"."); - CrossPlatformOperations.WriteToConfig("CustomEnvVar", customEnvVarTextBox.Text); - } - - /// Gets called when gets loaded. - /// Enables and changes colors for and accordingly. - private void CustomMirrorCheckLoadComplete(object sender, EventArgs e) + private void SaveButtonClickEvent(object sender, EventArgs e) { - bool enabled = (bool)customMirrorCheck.Checked; - customMirrorTextBox.Enabled = enabled; - mirrorDropDown.Enabled = !enabled; - if (OS.IsWindows) - mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive; + if (!IsProfileIndexValid()) + return; + ProfileXML profile = profileList[modSettingsProfileDropDown.SelectedIndex]; + log.Info("User opened the save directory for profile " + profile.Name + ", which is " + profile.SaveLocation); + CrossPlatformOperations.OpenFolder(profile.SaveLocation); } /// @@ -815,17 +871,17 @@ namespace AM2RLauncher DialogResult result = MessageBox.Show(this, HelperMethods.GetText(Text.DeleteModWarning, profile.Name), Text.WarningWindowTitle, MessageBoxButtons.OKCancel, MessageBoxType.Warning, MessageBoxDefaultButton.Cancel); - if (result == DialogResult.Ok) - { - log.Info("User did not cancel. Proceeding to delete " + profile); - DeleteProfileAndAdjustLists(profile); - log.Info(profile + " has been deleted"); - MessageBox.Show(this, HelperMethods.GetText(Text.DeleteModButtonSuccess, profile.Name), Text.SuccessWindowTitle); - } - else + // if user didn't press ok, cancel + if (result != DialogResult.Ok) { log.Info("User has cancelled profile deletion."); + return; } + + log.Info("User did not cancel. Proceeding to delete " + profile); + DeleteProfileAndAdjustLists(profile); + log.Info(profile + " has been deleted"); + MessageBox.Show(this, HelperMethods.GetText(Text.DeleteModButtonSuccess, profile.Name), Text.SuccessWindowTitle); } /// @@ -836,165 +892,98 @@ namespace AM2RLauncher { log.Info("User requested to update mod. Requesting user input for new mod .zip..."); - bool abort = false; - ProfileXML currentProfile = profileList[modSettingsProfileDropDown.SelectedIndex]; - OpenFileDialog fileFinder = GetSingleZipDialog(Text.SelectModFileDialog); + // If user didn't click OK, cancel if (fileFinder.ShowDialog(this) != DialogResult.Ok) { log.Info("User cancelled the Mod selection."); return; } - // Exit if nothing was selected - if (String.IsNullOrWhiteSpace(fileFinder.FileName)) - { - log.Info("Nothing was selected, cancelling mod update."); - LoadProfilesAndAdjustLists(); - return; - } - log.Info("User selected \"" + fileFinder.FileName + "\""); - // If either a directory was selected or the file somehow went missing, cancel + // If either a directory was selected, no file was selected or the file somehow went missing, cancel if (!File.Exists(fileFinder.FileName)) { log.Error("Selected mod .zip file not found! Cancelling mod update."); return; } - FileInfo modFile = new FileInfo(fileFinder.FileName); + //TODO: move most of this into AM2RLauncher.Profile? + FileInfo modFile = new FileInfo(fileFinder.FileName); string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName; - string extractedName = modFile.Name.Replace(".zip", "_new"); - string extractedFolder = modsDir + "/" + extractedName; - - // Extract it and see if it contains a profile.xml. If not, this is invalid + string extractedName = Path.GetFileNameWithoutExtension(modFile.Name) + "_new"; + string extractedModDir = modsDir + "/" + extractedName; - // If for some reason old files remain, delete them - if (Directory.Exists(extractedFolder)) - Directory.Delete(extractedFolder, true); + // If for some reason old files remain, delete them so that extraction doesnt throw + if (Directory.Exists(extractedModDir)) + Directory.Delete(extractedModDir, true); // Directory doesn't exist -> extract! - ZipFile.ExtractToDirectory(fileFinder.FileName, extractedFolder); + ZipFile.ExtractToDirectory(fileFinder.FileName, extractedModDir); - // Let's check if profile.xml exists in there! If it doesn't throw an error and cleanup - if (!File.Exists(extractedFolder + "/profile.xml")) + // If mod doesn't have a profile.xml, throw an error and cleanup + if (!File.Exists(extractedModDir + "/profile.xml")) { log.Error(fileFinder.FileName + " does not contain profile.xml! Cancelling mod update."); MessageBox.Show(this, HelperMethods.GetText(Text.ModIsInvalidMessage, extractedName), Text.ErrorWindowTitle, MessageBoxType.Error); - Directory.Delete(extractedFolder, true); - File.Delete(CrossPlatformOperations.CURRENTPATH + "/Mods/" + modFile.Name); + Directory.Delete(extractedModDir, true); return; } // Check by *name*, if the mod was installed already - ProfileXML profile = Serializer.Deserialize(File.ReadAllText(extractedFolder + "/profile.xml")); + ProfileXML profile = Serializer.Deserialize(File.ReadAllText(extractedModDir + "/profile.xml")); - if (profileList.FirstOrDefault(p => p.Name == profile.Name) != null || Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name)) + // If the selected mod is not installed, tell user that they should add it and cleanup + if (profileList.FirstOrDefault(p => p.Name == profile.Name) == null) { - // Mod is already installed, so we can update! - DialogResult updateResult = MessageBox.Show(this, HelperMethods.GetText(Text.UpdateModWarning, currentProfile.Name), Text.WarningWindowTitle, - MessageBoxButtons.OKCancel, MessageBoxType.Warning, MessageBoxDefaultButton.Cancel); - - if (updateResult == DialogResult.Ok) - { - // If the profile isn't installed, don't ask about archiving it - if (Profile.IsProfileInstalled(currentProfile)) - { - DialogResult archiveResult = MessageBox.Show(this, HelperMethods.GetText(Text.ArchiveMod, currentProfile.Name + " " + Text.VersionLabel + currentProfile.Version), Text.WarningWindowTitle, MessageBoxButtons.YesNo, MessageBoxType.Warning, MessageBoxDefaultButton.No); - - // User wants to archive profile - if (archiveResult == DialogResult.Yes) - ArchiveProfileAndAdjustLists(currentProfile); - } - // Now we delete the profile - DeleteProfileAndAdjustLists(currentProfile); - - // Rename directory to take the old one's place - string originalFolder = modsDir + "/" + extractedName.Replace("_new", ""); - Directory.Move(extractedFolder, originalFolder); - } - else // Cancel the operation! - { - log.Error("User has cancelled mod update!"); - abort = true; - } - } - else - { - // Cancel the operation! - // Show message to tell user that mod could not be found, install this separately log.Error("Mod is not installed! Cancelling mod update."); MessageBox.Show(this, HelperMethods.GetText(Text.UpdateModButtonWrongMod, currentProfile.Name).Replace("$SELECT", profile.Name), Text.WarningWindowTitle, MessageBoxButtons.OK); - abort = true; + HelperMethods.DeleteDirectory(extractedModDir); + return; } - - if (abort) + + // 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); + if (updateResult != DialogResult.Ok) { - // File cleanup - HelperMethods.DeleteDirectory(extractedFolder); - LoadProfilesAndAdjustLists(); + log.Error("User has cancelled mod update!"); + HelperMethods.DeleteDirectory(extractedModDir); return; } - log.Info("Successfully updated mod profile " + profile.Name + "."); - MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, currentProfile.Name), Text.SuccessWindowTitle); - UpdateStateMachine(); + // If the profile isn't installed, don't ask about archiving it + if (Profile.IsProfileInstalled(currentProfile)) + { + DialogResult archiveResult = MessageBox.Show(this, HelperMethods.GetText(Text.ArchiveMod, currentProfile.Name + " " + Text.VersionLabel + currentProfile.Version), Text.WarningWindowTitle, MessageBoxButtons.YesNo, MessageBoxType.Warning, MessageBoxDefaultButton.No); + // User wants to archive profile + if (archiveResult == DialogResult.Yes) + ArchiveProfileAndAdjustLists(currentProfile); + } + + DeleteProfileAndAdjustLists(currentProfile); + + // Rename directory to take the old one's place + string originalFolder = modsDir + "/" + Path.GetFileNameWithoutExtension(modFile.Name); + Directory.Move(extractedModDir, originalFolder); + + // Adjust our lists so it gets recognized LoadProfilesAndAdjustLists(); modSettingsProfileDropDown.SelectedIndex = profileList.FindIndex(p => p.Name == currentProfile.Name); if (modSettingsProfileDropDown.SelectedIndex == -1) modSettingsProfileDropDown.SelectedIndex = 0; - } - - /// - /// Gets called when user tries to close . This does a few things:
- /// 1) Writes the Width, Height and the check if is currently maximized to the Config
- /// 2) Checks if current is . If yes, it creates a Warning to the end user. - ///
- private void MainformClosing(object sender, CancelEventArgs e) - { - log.Info("Attempting to close MainForm!"); - - CrossPlatformOperations.WriteToConfig("Width", ClientSize.Width); - CrossPlatformOperations.WriteToConfig("Height", ClientSize.Height); - CrossPlatformOperations.WriteToConfig("IsMaximized", this.WindowState == WindowState.Maximized); - CrossPlatformOperations.WriteToConfig("ProfileIndex", profileIndex.ToString()); - switch (updateState) - { - case UpdateState.Downloading: - { - var result = MessageBox.Show(this, Text.CloseOnCloningText, Text.WarningWindowTitle, MessageBoxButtons.YesNo, - MessageBoxType.Warning, MessageBoxDefaultButton.No); - if (result == DialogResult.No) - { - e.Cancel = true; - } - else - isGitProcessGettingCancelled = true; - // We don't need to delete any folders here, the cancelled gitClone will do that automatically for us :) - break; - } - case UpdateState.Installing: - MessageBox.Show(this, Text.CloseOnInstallingText, Text.WarningWindowTitle, MessageBoxButtons.OK, MessageBoxType.Warning); - e.Cancel = true; - break; - } - - // This needs to be made invisible, otherwise a tray indicator will be visible (on linux?) that clicking crashes the application - trayIndicator.Visible = false; - - if (e.Cancel) - log.Info("Cancelled MainForm closing event during UpdateState." + updateState + "."); - else - log.Info("Successfully closed MainForm. Exiting main thread."); + log.Info("Successfully updated mod profile " + profile.Name + "."); + MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, currentProfile.Name), Text.SuccessWindowTitle); } + #endregion } } \ No newline at end of file diff --git a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs index 59de18c..9ec9529 100644 --- a/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs +++ b/AM2RLauncher/AM2RLauncher/MainForm/MainForm.UI.cs @@ -175,6 +175,7 @@ namespace AM2RLauncher colBGNoAlpha = Color.FromArgb(10, 10, 10); colBG = Color.FromArgb(10, 10, 10, 80); if (OS.IsLinux) colBG = colBGNoAlpha; // XORG can't display alpha anyway, and Wayland breaks with it. + // TODO: that sounds like an Eto bug. investigate, try to open eto issue. colBGHover = Color.FromArgb(17, 28, 13); Font smallButtonFont = new Font(SystemFont.Default, 10); @@ -808,9 +809,9 @@ namespace AM2RLauncher mirrorDropDown.SelectedIndexChanged += MirrorDropDownSelectedIndexChanged; profileLayout.LoadComplete += ProfileLayoutLoadComplete; addModButton.Click += AddModButtonClicked; - profileButton.Click += ProfilesButtonClickEvent; + profileButton.Click += ProfileDataButtonClickEvent; saveButton.Click += SaveButtonClickEvent; - modSettingsProfileDropDown.SelectedIndexChanged += SettingsProfileDropDownSelectedIndexChanged; + modSettingsProfileDropDown.SelectedIndexChanged += ModSettingsProfileDropDownSelectedIndexChanged; deleteModButton.Click += DeleteModButtonClicked; updateModButton.Click += UpdateModButtonClicked; profileDebugLogCheck.CheckedChanged += ProfileDebugLogCheckedChanged; @@ -836,6 +837,7 @@ namespace AM2RLauncher ButtonMenuItem showButton; /// of s, used for actually working with profile data. + //TODO: this should be moved into AM2RLauncher.Core List profileList; /// of s so that Eto's annoying interface is appeased. Used for profile name display in DropDowns. List profileNames; diff --git a/AM2RLauncher/AM2RLauncherCore/Profile.cs b/AM2RLauncher/AM2RLauncherCore/Profile.cs index 7c16c87..a03687e 100644 --- a/AM2RLauncher/AM2RLauncherCore/Profile.cs +++ b/AM2RLauncher/AM2RLauncherCore/Profile.cs @@ -47,13 +47,14 @@ public static class Profile /// /// Checks if AM2R 1.1 has been installed already, aka if a valid AM2R 1.1 Zip exists. + /// This method will store the result in a cache and return that, unless it's invalidated by . /// - /// Determines if the AM2R_11 Cache should be invalidated + /// Determines if the AM2R_11 Cache should be invalidated. /// public static bool Is11Installed(bool invalidateCache = false) { // Only invalidate if we need to - if (invalidateCache) InvalidateAM2R11InstallCacheIfNecessary(); + if (invalidateCache) InvalidateAM2R11InstallCache(); // If we have a cache, return that instead if (isAM2R11InstalledCache != null) return isAM2R11InstalledCache.Value; @@ -78,7 +79,7 @@ public static class Profile /// /// Invalidates if necessary. /// - private static void InvalidateAM2R11InstallCacheIfNecessary() + 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") && @@ -88,6 +89,64 @@ public static class Profile isAM2R11InstalledCache = null; } + /// + /// Checks if a Zip file is a valid AM2R_1.1 zip. + /// + /// Full Path to the Zip file to check. + /// detailing the result + public static IsZipAM2R11ReturnCodes CheckIfZipIsAM2R11(string zipPath) + { + const string d3dHash = "86e39e9161c3d930d93822f1563c280d"; + const string dataWinHash = "f2b84fe5ba64cb64e284be1066ca08ee"; + const string am2rHash = "15253f7a66d6ea3feef004ebbee9b438"; + + string tmpPath = Path.GetTempPath() + Path.GetFileNameWithoutExtension(zipPath); + + // Clean up in case folder exists already + if (Directory.Exists(tmpPath)) + Directory.Delete(tmpPath, true); + + Directory.CreateDirectory(tmpPath); + + // Open archive + ZipArchive am2rZip = ZipFile.OpenRead(zipPath); + + // Check if exe exists anywhere + ZipArchiveEntry am2rExe = am2rZip.Entries.FirstOrDefault(x => x.FullName.Contains("AM2R.exe")); + if (am2rExe == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; + // Check if it's not in a subfolder. if it'd be in a subfolder, fullname would be "folder/AM2R.exe" + if (am2rExe.FullName != "AM2R.exe") + return IsZipAM2R11ReturnCodes.GameIsInASubfolder; + // Check validity + am2rExe.ExtractToFile(tmpPath + "/" + am2rExe.FullName); + if (HelperMethods.CalculateMD5(tmpPath + "/" + am2rExe.FullName) != am2rHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; + + // Check if data.win exists / is valid + ZipArchiveEntry dataWin = am2rZip.Entries.FirstOrDefault(x => x.FullName == "data.win"); + if (dataWin == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; + dataWin.ExtractToFile(tmpPath + "/" + dataWin.FullName); + if (HelperMethods.CalculateMD5(tmpPath + "/" + dataWin.FullName) != dataWinHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; + + // Check if d3d.dll exists / is valid + ZipArchiveEntry d3dx = am2rZip.Entries.FirstOrDefault(x => x.FullName == "D3DX9_43.dll"); + if (d3dx == null) + return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX9_43Dll; + d3dx.ExtractToFile(tmpPath + "/" + d3dx.FullName); + if (HelperMethods.CalculateMD5(tmpPath + "/" + d3dx.FullName) != d3dHash) + return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX9_43Dll; + + // Clean up + Directory.Delete(tmpPath, true); + + // If we didn't exit before, everything is fine + log.Info("AM2R_11 check successful!"); + return IsZipAM2R11ReturnCodes.Successful; + } + /// /// Git Pulls from the repository. /// @@ -240,9 +299,7 @@ public static class Profile // Delete folder in Mods if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + profile.DataPath)) - { HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + profile.DataPath); - } // Delete the zip file in Mods if (File.Exists(CrossPlatformOperations.CURRENTPATH + profile.DataPath + ".zip")) @@ -254,9 +311,7 @@ public static class Profile // Delete folder in Profiles if (Directory.Exists(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name)) - { HelperMethods.DeleteDirectory(CrossPlatformOperations.CURRENTPATH + "/Profiles/" + profile.Name); - } log.Info("Successfully deleted profile " + profile.Name + "."); } @@ -497,6 +552,7 @@ public static class Profile progress.Report(100); return; } + log.Info("Creating Android APK for profile " + profile.Name + "."); // Create working dir after some cleanup @@ -782,62 +838,4 @@ public static class Profile // isValid seems to only check for a .git folder, and there are cases where that exists, but not the profile.xml return Repository.IsValid(CrossPlatformOperations.CURRENTPATH + "/PatchData") && File.Exists(CrossPlatformOperations.CURRENTPATH + "/PatchData/profile.xml"); } - - /// - /// Checks if a Zip file is a valid AM2R_1.1 zip. - /// - /// Full Path to the Zip file to check. - /// detailing the result - public static IsZipAM2R11ReturnCodes CheckIfZipIsAM2R11(string zipPath) - { - const string d3dHash = "86e39e9161c3d930d93822f1563c280d"; - const string dataWinHash = "f2b84fe5ba64cb64e284be1066ca08ee"; - const string am2rHash = "15253f7a66d6ea3feef004ebbee9b438"; - - string tmpPath = Path.GetTempPath() + Path.GetFileNameWithoutExtension(zipPath); - - // Clean up in case folder exists already - if (Directory.Exists(tmpPath)) - Directory.Delete(tmpPath, true); - - Directory.CreateDirectory(tmpPath); - - // Open archive - ZipArchive am2rZip = ZipFile.OpenRead(zipPath); - - // Check if exe exists anywhere - ZipArchiveEntry am2rExe = am2rZip.Entries.FirstOrDefault(x => x.FullName.Contains("AM2R.exe")); - if (am2rExe == null) - return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; - // Check if it's not in a subfolder. if it'd be in a subfolder, fullname would be "folder/AM2R.exe" - if (am2rExe.FullName != "AM2R.exe") - return IsZipAM2R11ReturnCodes.GameIsInASubfolder; - // Check validity - am2rExe.ExtractToFile(tmpPath + "/" + am2rExe.FullName); - if (HelperMethods.CalculateMD5(tmpPath + "/" + am2rExe.FullName) != am2rHash) - return IsZipAM2R11ReturnCodes.MissingOrInvalidAM2RExe; - - // Check if data.win exists / is valid - ZipArchiveEntry dataWin = am2rZip.Entries.FirstOrDefault(x => x.FullName == "data.win"); - if (dataWin == null) - return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; - dataWin.ExtractToFile(tmpPath + "/" + dataWin.FullName); - if (HelperMethods.CalculateMD5(tmpPath + "/" + dataWin.FullName) != dataWinHash) - return IsZipAM2R11ReturnCodes.MissingOrInvalidDataWin; - - // Check if d3d.dll exists / is valid - ZipArchiveEntry d3dx = am2rZip.Entries.FirstOrDefault(x => x.FullName == "D3DX9_43.dll"); - if (d3dx == null) - return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX9_43Dll; - d3dx.ExtractToFile(tmpPath + "/" + d3dx.FullName); - if (HelperMethods.CalculateMD5(tmpPath + "/" + d3dx.FullName) != d3dHash) - return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX9_43Dll; - - // Clean up - Directory.Delete(tmpPath, true); - - // If we didn't exit before, everything is fine - log.Info("AM2R_11 check successful!"); - return IsZipAM2R11ReturnCodes.Successful; - } } \ No newline at end of file