more reorga

- add some #regions
- rename some methods to be more clearer
- cleanup add and delete profile
pull/32/head
Miepee 4 years ago
parent 428387256f
commit 1b6d1469f9

@ -117,6 +117,107 @@ namespace AM2RLauncher
UpdateStateMachine();
}
#region Misc events
/// <summary>
/// Fires when the profile layout completes loading. This makes sure that if <see cref="modSettingsProfileDropDown"/> has nothing in it "on boot",
/// that everything is disabled.
/// </summary>
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;
}
/// <summary>
/// The <see cref="MainForm"/> calls this when you're resizing, in order to resize and scale the application accordingly.
/// </summary>
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);
}
/// <summary>
/// Gets called when user tries to close <see cref="MainForm"/>. This does a few things:<br/>
/// 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="UpdateState.Downloading"/>. If yes, it creates a Warning to the end user.
/// </summary>
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.");
}
/// <summary>Gets called when <see cref="showButton"/> gets clicked and shows the <see cref="MainForm"/> and brings it to the front again.</summary>
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
/// <summary>
/// Does a bunch of stuff, depending on the current state of <see cref="updateState"/>.
/// </summary>
@ -411,6 +512,28 @@ namespace AM2RLauncher
}
}
/// <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;
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
/// <summary>
/// If no internet access is available, this changes the content of <paramref name="tabPage"/> to an empty page only displaying <paramref name="errorLabel"/>.
/// </summary>
@ -432,376 +555,309 @@ namespace AM2RLauncher
};
}
/// <summary>
/// Runs when <see cref="addModButton"/> is clicked. Brings up a file select to select a mod, and adds that to the mod directory.
/// </summary>
private void AddModButtonClicked(object sender, EventArgs e)
#region SETTINGS
/// <summary>Gets called when user selects a different item from <see cref="languageDropDown"/> and writes that to the config.</summary>
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);
/// <summary>Gets called when <see cref="autoUpdateAM2RCheck"/> gets clicked and writes its new value to the config.</summary>
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)
/// <summary>Gets called when <see cref="autoUpdateLauncherCheck"/> gets clicked and writes its new value to the config.</summary>
private void AutoUpdateLauncherCheckChanged(object sender, EventArgs e)
{
log.Info("User cancelled the Mod selection.");
return;
log.Info("Auto Update Launcher has been set to " + autoUpdateAM2RCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("AutoUpdateLauncher", (bool)autoUpdateAM2RCheck.Checked);
}
if (String.IsNullOrWhiteSpace(fileFinder.FileName))
/// <summary>Gets called when <see cref="hqMusicPCCheck"/> gets clicked and writes its new value to the config.</summary>
private void HqMusicPCCheckChanged(object sender, EventArgs e)
{
log.Error("User did not supply valid input. Cancelling import.");
LoadProfilesAndAdjustLists();
return;
log.Info("PC HQ Music option has been changed to " + hqMusicPCCheck.Checked);
CrossPlatformOperations.WriteToConfig("MusicHQPC", hqMusicPCCheck.Checked);
}
log.Info("User selected \"" + fileFinder.FileName + "\"");
/// <summary>Gets called when <see cref="hqMusicAndroidCheck"/> gets clicked and writes its new value to the config.</summary>
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))
/// <summary>
/// Gets called when <see cref="profileDebugLogCheck"/> gets clicked, and writes it's new value to the config.
/// </summary>
private void ProfileDebugLogCheckedChanged(object sender, EventArgs e)
{
log.Error("Selected mod .zip file not found! Cancelling import.");
return;
log.Info("Create Game Debug Logs option has been set to " + profileDebugLogCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("ProfileDebugLog", profileDebugLogCheck.Checked);
}
FileInfo modFile = new FileInfo(fileFinder.FileName);
/// <summary>Gets called when user selects a different item from <see cref="mirrorDropDown"/>.
/// It then writes that to the config, and if <see cref="updateState"/> is not <see cref="UpdateState.Downloading"/>
/// it also overwrites the upstream URL in .git/config.</summary>
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<ProfileXML>(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;
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);
Regex gitURLRegex = new Regex("https://.*\\.git");
Match match = gitURLRegex.Match(gitConfig);
gitConfig = gitConfig.Replace(match.Value, currentMirror);
File.WriteAllText(gitConfigPath, gitConfig);
}
// Directory doesn't exist -> extract!
ZipFile.ExtractToDirectory(fileFinder.FileName, modsDir + "/" + extractedName);
log.Info("Imported and extracted mod .zip as " + extractedName);
// 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"))
/// <summary>Gets called when <see cref="customMirrorCheck"/> gets clicked, displays a warning <see cref="MessageBox"/>
/// and enables <see cref="customMirrorTextBox"/> accordingly.</summary>
private void CustomMirrorCheckChanged(object sender, EventArgs e)
{
log.Error(fileFinder.FileName + " does not contain profile.xml! Cancelling mod import.");
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;
}
log.Info("Use Custom Mirror option has been set to " + customMirrorCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("CustomMirrorEnabled", (bool)customMirrorCheck.Checked);
ProfileXML profile = Serializer.Deserialize<ProfileXML>(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;
//TODO: why exactly do we need this?
/// <summary>Gets called when <see cref="customMirrorCheck"/> gets loaded.
/// Enables and changes colors for <see cref="customMirrorTextBox"/> and <see cref="mirrorDropDown"/> accordingly.</summary>
private void CustomMirrorCheckLoadComplete(object sender, EventArgs e)
{
bool enabled = (bool)customMirrorCheck.Checked;
customMirrorTextBox.Enabled = enabled;
mirrorDropDown.Enabled = !enabled;
if (OS.IsWindows)
mirrorDropDown.TextColor = mirrorDropDown.Enabled ? colGreen : colInactive;
}
/// <summary>
/// This opens the game files directory for the current profile.
/// If the <see cref="customMirrorTextBox"/> has lost focus, we set its text as the new <see cref="currentMirror"/>.
/// </summary>
private void ProfilesButtonClickEvent(object sender, EventArgs e)
private void CustomMirrorTextBoxLostFocus(object sender, EventArgs e)
{
if (!IsProfileIndexValid())
// 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);
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);
}
/// <summary>
/// This opens the save directory for the current profile.
/// </summary>
private void SaveButtonClickEvent(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);
}
/// <summary>
/// Enabled / disables <see cref="updateModButton"/> and <see cref="deleteModButton"/> accordingly.
/// </summary>
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
{
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);
}
currentMirror = mirrorText;
CrossPlatformOperations.WriteToConfig("CustomMirrorText", currentMirror);
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);
log.Info("Overwriting mirror in gitconfig.");
if (modSettingsProfileDropDown.SelectedIndex < 0 || modSettingsProfileDropDown.Items.Count == 0)
return;
profileNotesTextArea.TextColor = colGreen;
profileNotesTextArea.Text = Text.ProfileNotes + "\n" + profileList[modSettingsProfileDropDown.SelectedIndex].ProfileNotes;
// 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 + ".");
}
/// <summary>
/// Fires when the profile layout completes loading. This makes sure that if <see cref="modSettingsProfileDropDown"/> has nothing in it "on boot",
/// that everything is disabled.
/// If <see cref="customEnvVarTextBox"/> has lost focus, we write its text to the config.
/// </summary>
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
/// <summary>
/// The <see cref="MainForm"/> calls this when you're resizing, in order to resize and scale the application accordingly.
/// Runs when <see cref="addModButton"/> is clicked. Brings up a file select to select a mod, and adds that to the mod directory.
/// </summary>
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;
// Do the actual scaling
e.Graphics.ScaleTransform(scale);
log.Info("User requested to add mod. Requesting user input for new mod .zip...");
// 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);
}
OpenFileDialog fileFinder = GetSingleZipDialog(Text.SelectModFileDialog);
/// <summary>Gets called when <see cref="showButton"/> gets clicked and shows the <see cref="MainForm"/> and brings it to the front again.</summary>
private void ShowButtonClick(object sender, EventArgs e)
// If user didn't press ok, cancel
if (fileFinder.ShowDialog(this) != DialogResult.Ok)
{
log.Info("User has opened the launcher from system tray.");
this.Show();
this.BringToFront();
log.Info("User cancelled the Mod selection.");
return;
}
/// <summary>Gets called when <see cref="hqMusicPCCheck"/> gets clicked and writes its new value to the config.</summary>
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 + "\"");
/// <summary>Gets called when <see cref="hqMusicAndroidCheck"/> gets clicked and writes its new value to the config.</summary>
private void HqMusicAndroidCheckChanged(object sender, EventArgs e)
// 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.Info("Android HQ Music option has been changed to " + hqMusicAndroidCheck.Checked);
CrossPlatformOperations.WriteToConfig("MusicHQAndroid", hqMusicAndroidCheck.Checked);
log.Error("Selected mod .zip file not found! Cancelling import.");
return;
}
/// <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;
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;
//TODO: move most of this into AM2RLauncher.Profile?
UpdateStateMachine();
}
FileInfo modFile = new FileInfo(fileFinder.FileName);
string modsDir = new DirectoryInfo(CrossPlatformOperations.CURRENTPATH + "/Mods").FullName;
string modFileName = Path.GetFileNameWithoutExtension(modFile.Name);
string extractedModDir = modsDir + "/" + modFileName;
/// <summary>Gets called when user selects a different item from <see cref="languageDropDown"/> and writes that to the config.</summary>
private void LanguageDropDownSelectedIndexChanged(object sender, EventArgs e)
// Check first, if the directory is already there, if yes, throw error
if (Directory.Exists(extractedModDir))
{
log.Info("languageDropDown.SelectedIndex has been changed to " + languageDropDown.SelectedIndex + ".");
CrossPlatformOperations.WriteToConfig("Language", languageDropDown.SelectedIndex == 0 ? "Default" : languageDropDown.Items[languageDropDown.SelectedIndex].Text);
string existingProfileName = Serializer.Deserialize<ProfileXML>(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;
}
/// <summary>Gets called when <see cref="autoUpdateAM2RCheck"/> gets clicked and writes its new value to the config.</summary>
private void AutoUpdateAM2RCheckChanged(object sender, EventArgs e)
{
log.Info("Auto Update AM2R has been set to " + autoUpdateAM2RCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("AutoUpdateAM2R", (bool)autoUpdateAM2RCheck.Checked);
}
// Directory doesn't exist -> extract!
ZipFile.ExtractToDirectory(modFile.FullName, extractedModDir);
log.Info("Imported and extracted mod .zip as " + modFileName);
/// <summary>Gets called when <see cref="autoUpdateLauncherCheck"/> gets clicked and writes its new value to the config.</summary>
private void AutoUpdateLauncherCheckChanged(object sender, EventArgs e)
// If profile.xml doesn't exist, throw an error and cleanup
if (!File.Exists(extractedModDir + "/profile.xml"))
{
log.Info("Auto Update Launcher has been set to " + autoUpdateAM2RCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("AutoUpdateLauncher", (bool)autoUpdateAM2RCheck.Checked);
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;
}
/// <summary>Gets called when <see cref="customMirrorCheck"/> gets clicked, displays a warning <see cref="MessageBox"/>
/// and enables <see cref="customMirrorTextBox"/> accordingly.</summary>
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);
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;
ProfileXML profile = Serializer.Deserialize<ProfileXML>(File.ReadAllText(extractedModDir + "/profile.xml"));
// Create warning dialog when enabling
if (enabled)
{
MessageBox.Show(this, Text.WarningWindowText, Text.WarningWindowTitle, MessageBoxType.Warning);
currentMirror = customMirrorTextBox.Text;
}
else
// If OS versions mismatch, throw error and cleanup
if (OS.Name != profile.OperatingSystem)
{
// Revert mirror to selected index in mirror dropdown
currentMirror = mirrorList[mirrorDropDown.SelectedIndex];
}
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;
}
/// <summary>Gets called when user selects a different item from <see cref="mirrorDropDown"/>.
/// It then writes that to the config, and if <see cref="updateState"/> is not <see cref="UpdateState.Downloading"/>
/// it also overwrites the upstream URL in .git/config.</summary>
private void MirrorDropDownSelectedIndexChanged(object sender, EventArgs e)
// If mod was installed/added by *name* already, throw error and cleanup
if (profileList.FirstOrDefault(p => p.Name == profile.Name) != null)
{
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.Error(profile.Name + " is already installed.");
MessageBox.Show(this, HelperMethods.GetText(Text.ModIsAlreadyInstalledMessage, profile.Name), Text.WarningWindowTitle, MessageBoxType.Warning);
HelperMethods.DeleteDirectory(extractedModDir);
return;
}
log.Info("Overwriting mirror in gitconfig.");
// 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;
// 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);
log.Info(profile.Name + " successfully added.");
MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, profile.Name), Text.SuccessWindowTitle);
}
/// <summary>
/// Gets called when <see cref="profileDebugLogCheck"/> gets clicked, and writes it's new value to the config.
/// Enabled / disables <see cref="updateModButton"/> and <see cref="deleteModButton"/> accordingly.
/// </summary>
private void ProfileDebugLogCheckedChanged(object sender, EventArgs e)
private void ModSettingsProfileDropDownSelectedIndexChanged(object sender, EventArgs e)
{
log.Info("Create Game Debug Logs option has been set to " + profileDebugLogCheck.Checked + ".");
CrossPlatformOperations.WriteToConfig("ProfileDebugLog", profileDebugLogCheck.Checked);
}
if (modSettingsProfileDropDown.SelectedIndex == -1 && modSettingsProfileDropDown.Items.Count == 0) return;
/// <summary>
/// If the <see cref="customMirrorTextBox"/> has lost focus, we set its text as the new <see cref="currentMirror"/>.
/// </summary>
private void CustomMirrorTextBoxLostFocus(object sender, EventArgs e)
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)
{
// 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 = false;
deleteModButton.ToolTip = null;
updateModButton.Enabled = false;
updateModButton.ToolTip = null;
profileNotesTextArea.TextColor = colInactive;
}
else
{
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;
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);
}
currentMirror = mirrorText;
CrossPlatformOperations.WriteToConfig("CustomMirrorText", currentMirror);
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);
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;
log.Info("Custom Mirror has been set to " + currentMirror + ".");
}
/// <summary>
/// If <see cref="customEnvVarTextBox"/> has lost focus, we write its text to the config.
/// This opens the game files directory for the current profile.
/// </summary>
private void CustomEnvVarTextBoxLostFocus(object sender, EventArgs e)
private void ProfileDataButtonClickEvent(object sender, EventArgs e)
{
log.Info("Custom Environment variables have been set to \"" + customEnvVarTextBox.Text + "\".");
CrossPlatformOperations.WriteToConfig("CustomEnvVar", customEnvVarTextBox.Text);
if (!IsProfileIndexValid())
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);
}
/// <summary>Gets called when <see cref="customMirrorCheck"/> gets loaded.
/// Enables and changes colors for <see cref="customMirrorTextBox"/> and <see cref="mirrorDropDown"/> accordingly.</summary>
private void CustomMirrorCheckLoadComplete(object sender, EventArgs e)
/// <summary>
/// This opens the save directory for the current profile.
/// </summary>
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);
}
/// <summary>
@ -815,18 +871,18 @@ 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)
// 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);
}
else
{
log.Info("User has cancelled profile deletion.");
}
}
/// <summary>
/// Gets called, when <see cref="updateModButton"/> gets clicked. Opens a window, so the user can select a zip, which will be updated over
@ -836,71 +892,71 @@ 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;
string extractedName = Path.GetFileNameWithoutExtension(modFile.Name) + "_new";
string extractedModDir = modsDir + "/" + extractedName;
// Extract it and see if it contains a profile.xml. If not, this is invalid
// 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<ProfileXML>(File.ReadAllText(extractedFolder + "/profile.xml"));
ProfileXML profile = Serializer.Deserialize<ProfileXML>(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!
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);
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);
if (updateResult == DialogResult.Ok)
if (updateResult != DialogResult.Ok)
{
log.Error("User has cancelled mod update!");
HelperMethods.DeleteDirectory(extractedModDir);
return;
}
// If the profile isn't installed, don't ask about archiving it
if (Profile.IsProfileInstalled(currentProfile))
{
@ -910,91 +966,24 @@ namespace AM2RLauncher
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;
}
if (abort)
{
// File cleanup
HelperMethods.DeleteDirectory(extractedFolder);
LoadProfilesAndAdjustLists();
return;
}
log.Info("Successfully updated mod profile " + profile.Name + ".");
MessageBox.Show(this, HelperMethods.GetText(Text.ModSuccessfullyInstalledMessage, currentProfile.Name), Text.SuccessWindowTitle);
UpdateStateMachine();
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;
}
/// <summary>
/// Gets called when user tries to close <see cref="MainForm"/>. This does a few things:<br/>
/// 1) Writes the Width, Height and the check if <see cref="MainForm"/> is currently maximized to the Config<br/>
/// 2) Checks if current <see cref="updateState"/> is <see cref="UpdateState.Downloading"/>. If yes, it creates a Warning to the end user.
/// </summary>
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
}
}

@ -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;
/// <summary><see cref="List{T}"/> of <see cref="ProfileXML"/>s, used for actually working with profile data.</summary>
//TODO: this should be moved into AM2RLauncher.Core
List<ProfileXML> profileList;
/// <summary><see cref="List{T}"/> of <see cref="ListItem"/>s so that Eto's annoying <see cref="IListItem"/> interface is appeased. Used for profile name display in DropDowns.</summary>
List<ListItem> profileNames;

@ -47,13 +47,14 @@ public static class Profile
/// <summary>
/// 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 <paramref name="invalidateCache"/>.
/// </summary>
/// <param name="invalidateCache">Determines if the AM2R_11 Cache should be invalidated</param>
/// <param name="invalidateCache">Determines if the AM2R_11 Cache should be invalidated.</param>
/// <returns></returns>
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
/// <summary>
/// Invalidates <see cref="isAM2R11InstalledCache"/> if necessary.
/// </summary>
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;
}
/// <summary>
/// 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>
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;
}
/// <summary>
/// Git Pulls from the repository.
/// </summary>
@ -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");
}
/// <summary>
/// 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>
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;
}
}
Loading…
Cancel
Save