From b2e7ad697a83556aae17ac6a2b6db9338b0f296a Mon Sep 17 00:00:00 2001 From: Miepee <38186597+Miepee@users.noreply.github.com> Date: Sat, 21 May 2022 20:48:31 +0200 Subject: [PATCH] Lib: use string interpolation + clean up archiveProfile --- AM2RLauncher/AM2RLauncherCore/Profile.cs | 335 +++++++++++------------ 1 file changed, 167 insertions(+), 168 deletions(-) diff --git a/AM2RLauncher/AM2RLauncherCore/Profile.cs b/AM2RLauncher/AM2RLauncherCore/Profile.cs index cef8d49..32ac958 100644 --- a/AM2RLauncher/AM2RLauncherCore/Profile.cs +++ b/AM2RLauncher/AM2RLauncherCore/Profile.cs @@ -8,6 +8,7 @@ using System.IO.Compression; using System.Linq; using System.Text.RegularExpressions; using AM2RLauncherLib.XML; +using log4net.Util; namespace AM2RLauncherLib; @@ -28,7 +29,6 @@ public enum IsZipAM2R11ReturnCodes /// public static class Profile { - /// /// The logger for , used to write any caught exceptions. /// @@ -66,7 +66,7 @@ public static class Profile // Check if it's valid, if not log it, rename it and silently leave if (returnCode != IsZipAM2R11ReturnCodes.Successful) { - log.Info("Detected invalid AM2R_11 zip with following error code: " + returnCode); + log.Info($"Detected invalid AM2R_11 zip with following error code: {returnCode}"); HelperMethods.RecursiveRollover(am2r11file); isAM2R11InstalledCache = false; return false; @@ -117,24 +117,24 @@ public static class Profile if (am2rExe.FullName != "AM2R.exe") return IsZipAM2R11ReturnCodes.GameIsInASubfolder; // Check validity - am2rExe.ExtractToFile(tmpPath + "/" + am2rExe.FullName); - if (HelperMethods.CalculateMD5(tmpPath + "/" + am2rExe.FullName) != am2rHash) + 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) + 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.MissingOrInvalidD3DX943Dll; - d3dx.ExtractToFile(tmpPath + "/" + d3dx.FullName); - if (HelperMethods.CalculateMD5(tmpPath + "/" + d3dx.FullName) != d3dHash) + d3dx.ExtractToFile($"{tmpPath}/{d3dx.FullName}"); + if (HelperMethods.CalculateMD5($"{tmpPath}/{d3dx.FullName}") != d3dHash) return IsZipAM2R11ReturnCodes.MissingOrInvalidD3DX943Dll; // Clean up @@ -193,9 +193,9 @@ public static class Profile List profileList = new List(); // Check for and add the Community Updates profile - if (File.Exists(Core.PatchDataPath + "/profile.xml")) + if (File.Exists($"{Core.PatchDataPath}/profile.xml")) { - ProfileXML profile = Serializer.Deserialize(File.ReadAllText(Core.PatchDataPath + "/profile.xml")); + ProfileXML profile = Serializer.Deserialize(File.ReadAllText($"{Core.PatchDataPath}/profile.xml")); profile.DataPath = "/PatchData/data"; profileList.Add(profile); } @@ -211,79 +211,78 @@ public static class Profile foreach (DirectoryInfo dir in modsDir.GetDirectories()) { // If no profile.xml exists we don't add anything - if (!File.Exists(dir.FullName + "/profile.xml")) + if (!File.Exists($"{dir.FullName}/profile.xml")) continue; - ProfileXML prof = Serializer.Deserialize(File.ReadAllText(dir.FullName + "/profile.xml")); + ProfileXML prof = Serializer.Deserialize(File.ReadAllText($"{dir.FullName}/profile.xml")); // Safety check for non-installable profiles if (prof.Installable || IsProfileInstalled(prof)) { - prof.DataPath = "/Mods/" + dir.Name; + prof.DataPath = $"/Mods/{dir.Name}"; profileList.Add(prof); } // If not installable and isn't installed, remove it else if (!IsProfileInstalled(prof)) { - prof.DataPath = "/Mods/" + dir.Name; + prof.DataPath = $"/Mods/{dir.Name}"; DeleteProfile(prof); } } - log.Info("Loaded " + profileList.Count + " profile(s)."); + log.Info($"Loaded {profileList.Count} profile(s)."); return profileList; } /// - /// Archives a given Profile by making a copy with "Name (version)". Does silently nothing if user archives already exist + /// Archives a given Profile by making a copy with "Name (version)". Silently does nothing if user archives already exist. /// /// The profile to archive public static void ArchiveProfile(ProfileXML profile) { - // temporarily serialize and deserialize to essentially "clone" the variable as otherwise we'd modify references - File.WriteAllText(Path.GetTempPath() + "/" + profile.Name, Serializer.Serialize(profile)); - profile = Serializer.Deserialize(File.ReadAllText(Path.GetTempPath() + "/" + profile.Name)); + // Temporarily serialize and deserialize to essentially "clone" the variable as otherwise we'd modify references + File.WriteAllText($"{Path.GetTempPath()}/{profile.Name}", Serializer.Serialize(profile)); + profile = Serializer.Deserialize(File.ReadAllText($"{Path.GetTempPath()}/{profile.Name}")); string originalName = profile.Name; // Change name to include version and be unique - profile.Name += " (" + profile.Version + ")"; + profile.Name += $" ({profile.Version})"; // if we're archiving community updates, remove the "latest" part profile.Name = profile.Name.Replace("Community Updates Latest", "Community Updates"); - log.Info("Archiving " + profile.Name); + log.Info($"Archiving {profile.Name}"); - string profileArchivePath = Core.ProfilesPath + "/" + profile.Name; + // Rename directory in the profiles folder + string profileArchivePath = $"{Core.ProfilesPath}/{profile.Name}"; - // Do NOT overwrite if a path with this name already exists! It is likely an existing user archive. - if (!Directory.Exists(profileArchivePath)) + // If our desired rename already exists, it's probably a user archive... + // so we just delete the original folder and move on. + if (Directory.Exists(profileArchivePath)) { - // Rename current profile if we have it installed - if (Directory.Exists(Core.ProfilesPath + "/" + originalName)) - Directory.Move(Core.ProfilesPath + "/" + originalName, profileArchivePath); + HelperMethods.DeleteDirectory($"{Core.ProfilesPath}/{originalName}"); + log.Info("Cancelling archival! User-defined archive in Profiles already exists."); + return; + } - // Set as non-installable so that it's just treated as a launching reference - profile.Installable = false; + // Rename current profile if we have it installed + if (Directory.Exists($"{Core.ProfilesPath}/{originalName}")) + Directory.Move($"{Core.ProfilesPath}/{originalName}", profileArchivePath); - string modArchivePath = Core.ModsPath + "/" + profile.Name; + // Set as non-installable so that it's just treated as a launching reference + profile.Installable = false; - // Do NOT overwrite if a path with this name already exists! It is likely an existing user archive. - if (!Directory.Exists(modArchivePath)) - { - Directory.CreateDirectory(modArchivePath); - File.WriteAllText(modArchivePath + "/profile.xml", Serializer.Serialize(profile)); - log.Info("Finished archival."); - } - else - { - HelperMethods.DeleteDirectory(profileArchivePath); - log.Info("Cancelling archival! User-defined archive in Mods already exists."); - } - } - // If our desired rename already exists, it's probably a user archive... so we just delete the original folder and move on with installation of the new version. - else + // Try archiving profile as a mod + string modArchivePath = $"{Core.ModsPath}/{profile.Name}"; + + if (Directory.Exists(modArchivePath)) { - HelperMethods.DeleteDirectory(Core.ProfilesPath + "/" + originalName); - log.Info("Cancelling archival! User-defined archive in Profiles already exists."); + HelperMethods.DeleteDirectory(profileArchivePath); + log.Info("Cancelling archival! User-defined archive in Mods already exists."); + return; } + + Directory.CreateDirectory(modArchivePath); + File.WriteAllText($"{modArchivePath}/profile.xml", Serializer.Serialize(profile)); + log.Info("Finished archival."); } /// @@ -292,25 +291,25 @@ public static class Profile /// The profile to delete. public static void DeleteProfile(ProfileXML profile) { - log.Info("Attempting to delete profile " + profile.Name + "..."); + log.Info($"Attempting to delete profile {profile.Name}..."); // 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")) + if (File.Exists($"{CrossPlatformOperations.CurrentPath}{profile.DataPath}.zip")) { // For some reason, it was set at read only, so we undo that here - File.SetAttributes(CrossPlatformOperations.CurrentPath + profile.DataPath + ".zip", FileAttributes.Normal); - File.Delete(CrossPlatformOperations.CurrentPath + profile.DataPath + ".zip"); + File.SetAttributes($"{CrossPlatformOperations.CurrentPath}{profile.DataPath}.zip", FileAttributes.Normal); + File.Delete($"{CrossPlatformOperations.CurrentPath}{profile.DataPath}.zip"); } // Delete folder in Profiles - if (Directory.Exists(Core.ProfilesPath + "/" + profile.Name)) - HelperMethods.DeleteDirectory(Core.ProfilesPath + "/" + profile.Name); + if (Directory.Exists($"{Core.ProfilesPath}/{profile.Name}")) + HelperMethods.DeleteDirectory($"{Core.ProfilesPath}/{profile.Name}"); - log.Info("Successfully deleted profile " + profile.Name + "."); + log.Info($"Successfully deleted profile {profile.Name}."); } /// @@ -321,10 +320,10 @@ public static class Profile /// Provides the current progress of this method. public static void InstallProfile(ProfileXML profile, bool useHqMusic, IProgress progress) { - log.Info("Installing profile " + profile.Name + "..."); + log.Info($"Installing profile {profile.Name}..."); string profilesHomePath = Core.ProfilesPath; - string profilePath = profilesHomePath + "/" + profile.Name; + string profilePath = $"{profilesHomePath}/{profile.Name}"; // Failsafe for Profiles directory if (!Directory.Exists(profilesHomePath)) @@ -352,8 +351,8 @@ public static class Profile // -Resources (asset path) profilePath += "/AM2R.app/Contents"; Directory.CreateDirectory(profilePath); - Directory.CreateDirectory(profilePath + "/MacOS"); - Directory.CreateDirectory(profilePath + "/Resources"); + Directory.CreateDirectory($"{profilePath}/MacOS"); + Directory.CreateDirectory($"{profilePath}/Resources"); profilePath += "/Resources"; log.Info("ProfileInstallation: Created folder structure."); @@ -381,9 +380,9 @@ public static class Profile { dataWin = "game.unx"; // Use the exe name based on the desktop file in the AppImage, rather than hard coding it. - string desktopContents = File.ReadAllText(Core.PatchDataPath + "/data/AM2R.AppDir/AM2R.desktop"); + string desktopContents = File.ReadAllText($"{Core.PatchDataPath}/data/AM2R.AppDir/AM2R.desktop"); exe = Regex.Match(desktopContents, @"(?<=Exec=).*").Value; - log.Info("According to AppImage desktop file, using \"" + exe + "\" as game name."); + log.Info($"According to AppImage desktop file, using \"{exe}\" as game name."); } else if (OS.IsMac) { @@ -392,48 +391,48 @@ public static class Profile } else { - log.Error(OS.Name + " does not have valid runner / data.win names!"); + log.Error($"{OS.Name} does not have valid runner / data.win names!"); } - log.Info("Attempting to patch in " + profilePath); + log.Info($"Attempting to patch in {profilePath}"); if (OS.IsWindows) { // Patch game executable if (profile.UsesYYC) { - CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/data.win", dataPath + "/AM2R.xdelta", profilePath + "/" + exe); + CrossPlatformOperations.ApplyXdeltaPatch($"{profilePath}/data.win", $"{dataPath}/AM2R.xdelta", $"{profilePath}/{exe}"); // Delete 1.1's data.win, we don't need it anymore! - File.Delete(profilePath + "/data.win"); + File.Delete($"{profilePath}/data.win"); } else { - CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/data.win", dataPath + "/data.xdelta", profilePath + "/" + dataWin); - CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/AM2R.exe", dataPath + "/AM2R.xdelta", profilePath + "/" + exe); + CrossPlatformOperations.ApplyXdeltaPatch($"{profilePath}/data.win", $"{dataPath}/data.xdelta", $"{profilePath}/{dataWin}"); + CrossPlatformOperations.ApplyXdeltaPatch($"{profilePath}/AM2R.exe", $"{dataPath}/AM2R.xdelta", $"{profilePath}/{exe}"); } } else if (OS.IsUnix) // YYC and VM look exactly the same on Linux and Mac so we're all good here. { - CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/data.win", dataPath + "/game.xdelta", profilePath + "/" + dataWin); - CrossPlatformOperations.ApplyXdeltaPatch(profilePath + "/AM2R.exe", dataPath + "/AM2R.xdelta", profilePath + "/" + exe); + CrossPlatformOperations.ApplyXdeltaPatch($"{profilePath}/data.win", $"{dataPath}/game.xdelta", $"{profilePath}/{dataWin}"); + CrossPlatformOperations.ApplyXdeltaPatch($"{profilePath}/AM2R.exe", $"{dataPath}/AM2R.xdelta", $"{profilePath}/{exe}"); // Just in case the resulting file isn't chmod-ed... - Process.Start("chmod", "+x \"" + profilePath + "/" + exe + "\"")?.WaitForExit(); + Process.Start("chmod", $"+x \"{profilePath}/{exe}\"")?.WaitForExit(); // These are not needed by linux or Mac at all, so we delete them - File.Delete(profilePath + "/data.win"); - File.Delete(profilePath + "/AM2R.exe"); - File.Delete(profilePath + "/D3DX9_43.dll"); + File.Delete($"{profilePath}/data.win"); + File.Delete($"{profilePath}/AM2R.exe"); + File.Delete($"{profilePath}/D3DX9_43.dll"); // Move exe one directory out on Linux, move to MacOS folder instead on Mac if (OS.IsLinux) - File.Move(profilePath + "/" + exe, profilePath.Substring(0, profilePath.LastIndexOf("/")) + "/" + exe); + File.Move($"{profilePath}/{exe}", $"{profilePath.Substring(0, profilePath.LastIndexOf("/"))}/{exe}"); else - File.Move(profilePath + "/" + exe, profilePath.Replace("Resources", "MacOS") + "/" + exe); + File.Move($"{profilePath}/{exe}", $"{profilePath.Replace("Resources", "MacOS")}/{exe}"); } else { - log.Error(OS.Name + " does not have patching methods!"); + log.Error($"{OS.Name} does not have patching methods!"); } // Applied patch @@ -442,11 +441,11 @@ public static class Profile log.Info("xdelta patch(es) applied."); // Install new datafiles - HelperMethods.DirectoryCopy(dataPath + "/files_to_copy", profilePath); + HelperMethods.DirectoryCopy($"{dataPath}/files_to_copy", profilePath); // HQ music if (!profile.UsesCustomMusic && useHqMusic) - HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/HDR_HQ_in-game_music", profilePath); + HelperMethods.DirectoryCopy($"{Core.PatchDataPath}/data/HDR_HQ_in-game_music", profilePath); // Linux post-process @@ -458,20 +457,20 @@ public static class Profile // Rename all songs to lowercase foreach (FileInfo file in new DirectoryInfo(assetsPath).GetFiles()) { - if (file.Name.EndsWith(".ogg") && !File.Exists(file.DirectoryName + "/" + file.Name.ToLower())) - File.Move(file.FullName, file.DirectoryName + "/" + file.Name.ToLower()); + if (file.Name.EndsWith(".ogg") && !File.Exists($"{file.DirectoryName}/{file.Name.ToLower()}")) + File.Move(file.FullName, $"{file.DirectoryName}/{file.Name.ToLower()}"); } // Copy AppImage template to here - HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/AM2R.AppDir", profilePath + "/AM2R.AppDir/"); + HelperMethods.DirectoryCopy($"{Core.PatchDataPath}/data/AM2R.AppDir", $"{profilePath}/AM2R.AppDir/"); // Safety checks, in case the folders don't exist - Directory.CreateDirectory(profilePath + "/AM2R.AppDir/usr/bin/"); - Directory.CreateDirectory(profilePath + "/AM2R.AppDir/usr/bin/assets/"); + Directory.CreateDirectory($"{profilePath}/AM2R.AppDir/usr/bin/"); + Directory.CreateDirectory($"{profilePath}/AM2R.AppDir/usr/bin/assets/"); // Copy game assets to the AppImageDir - HelperMethods.DirectoryCopy(assetsPath, profilePath + "/AM2R.AppDir/usr/bin/assets/"); - File.Copy(profilePath + "/" + exe, profilePath + "/AM2R.AppDir/usr/bin/" + exe); + HelperMethods.DirectoryCopy(assetsPath, $"{profilePath}/AM2R.AppDir/usr/bin/assets/"); + File.Copy($"{profilePath}/{exe}", $"{profilePath}/AM2R.AppDir/usr/bin/{exe}"); progress.Report(66); log.Info("Gtk-specific formatting finished."); @@ -482,16 +481,16 @@ public static class Profile Directory.SetCurrentDirectory(profilePath); Console.SetError(new StreamWriter(Stream.Null)); Environment.SetEnvironmentVariable("ARCH", "x86_64"); - Process.Start(Core.PatchDataPath + "/utilities/appimagetool-x86_64.AppImage", "-n AM2R.AppDir")?.WaitForExit(); + Process.Start($"{Core.PatchDataPath}/utilities/appimagetool-x86_64.AppImage", "-n AM2R.AppDir")?.WaitForExit(); Directory.SetCurrentDirectory(workingDir); Console.SetError(cliError); // Clean files - Directory.Delete(profilePath + "/AM2R.AppDir", true); + Directory.Delete($"{profilePath}/AM2R.AppDir", true); Directory.Delete(assetsPath, true); - File.Delete(profilePath + "/" + exe); - if (File.Exists(profilePath + "/AM2R.AppImage")) File.Delete(profilePath + "/AM2R.AppImage"); - File.Move(profilePath + "/" + "AM2R-x86_64.AppImage", profilePath + "/AM2R.AppImage"); + File.Delete($"{profilePath}/{exe}"); + if (File.Exists($"{profilePath}/AM2R.AppImage")) File.Delete($"{profilePath}/AM2R.AppImage"); + File.Move($"{profilePath}/AM2R-x86_64.AppImage", $"{profilePath}/AM2R.AppImage"); } // Mac post-process else if (OS.IsMac) @@ -499,33 +498,33 @@ public static class Profile // Rename all songs to lowercase foreach (FileInfo file in new DirectoryInfo(profilePath).GetFiles()) { - if (file.Name.EndsWith(".ogg") && !File.Exists(file.DirectoryName + "/" + file.Name.ToLower())) - File.Move(file.FullName, file.DirectoryName + "/" + file.Name.ToLower()); + if (file.Name.EndsWith(".ogg") && !File.Exists($"{file.DirectoryName}/{file.Name.ToLower()}")) + File.Move(file.FullName, $"{file.DirectoryName}/{file.Name.ToLower()}"); } // Loading custom fonts crashes on Mac, so we delete those if they exist - if (Directory.Exists(profilePath + "/lang/fonts")) - Directory.Delete(profilePath + "/lang/fonts", true); + if (Directory.Exists($"{profilePath}/lang/fonts")) + Directory.Delete($"{profilePath}/lang/fonts", true); // Move Frameworks, Info.plist and PkgInfo over - HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/Frameworks", profilePath.Replace("Resources", "Frameworks")); - File.Copy(dataPath + "/Info.plist", profilePath.Replace("Resources", "") + "/Info.plist", true); - File.Copy(Core.PatchDataPath + "/data/PkgInfo", profilePath.Replace("Resources", "") + "/PkgInfo", true); + HelperMethods.DirectoryCopy($"{Core.PatchDataPath}/data/Frameworks", profilePath.Replace("Resources", "Frameworks")); + File.Copy($"{dataPath}/Info.plist", $"{profilePath.Replace("Resources", "")}/Info.plist", true); + File.Copy($"{Core.PatchDataPath}/data/PkgInfo", $"{profilePath.Replace("Resources", "")}/PkgInfo", true); //Put profilePath back to what it was before - profilePath = profilesHomePath + "/" + profile.Name; + profilePath = $"{profilesHomePath}/{profile.Name}"; } // Copy profile.xml so we can grab data to compare for updates later! // tldr; check if we're in PatchData or not if (new DirectoryInfo(dataPath).Parent?.Name == "PatchData") - File.Copy(dataPath + "/../profile.xml", profilePath + "/profile.xml"); + File.Copy($"{dataPath}/../profile.xml", $"{profilePath}/profile.xml"); else - File.Copy(dataPath + "/profile.xml", profilePath + "/profile.xml"); + File.Copy($"{dataPath}/profile.xml", $"{profilePath}/profile.xml"); // Installed datafiles progress.Report(100); - log.Info("Successfully installed profile " + profile.Name + "."); + log.Info($"Successfully installed profile {profile.Name}."); } /// @@ -535,11 +534,11 @@ public static class Profile /// if yes, if not. public static bool IsProfileInstalled(ProfileXML profile) { - if (OS.IsWindows) return File.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.exe"); - if (OS.IsLinux) return File.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.AppImage"); - if (OS.IsMac) return Directory.Exists(Core.ProfilesPath + "/" + profile.Name + "/AM2R.app"); + if (OS.IsWindows) return File.Exists($"{Core.ProfilesPath}/{profile.Name}/AM2R.exe"); + if (OS.IsLinux) return File.Exists($"{Core.ProfilesPath}/{profile.Name}/AM2R.AppImage"); + if (OS.IsMac) return Directory.Exists($"{Core.ProfilesPath}/{profile.Name}/AM2R.app"); - log.Error(OS.Name + " can't have profiles installed!"); + log.Error($"{OS.Name} can't have profiles installed!"); return false; } @@ -558,12 +557,12 @@ public static class Profile return; } - log.Info("Creating Android APK for profile " + profile.Name + "."); + log.Info($"Creating Android APK for profile {profile.Name}."); // Create working dir after some cleanup - string apktoolPath = Core.PatchDataPath + "/utilities/android/apktool.jar", - uberPath = Core.PatchDataPath + "/utilities/android/uber-apk-signer.jar", - tempDir = new DirectoryInfo(CrossPlatformOperations.CurrentPath + "/temp").FullName, + string apktoolPath = $"{Core.PatchDataPath}/utilities/android/apktool.jar", + uberPath = $"{Core.PatchDataPath}/utilities/android/uber-apk-signer.jar", + tempDir = new DirectoryInfo($"{CrossPlatformOperations.CurrentPath}/temp").FullName, dataPath = CrossPlatformOperations.CurrentPath + profile.DataPath; if (Directory.Exists(tempDir)) Directory.Delete(tempDir, true); @@ -573,64 +572,64 @@ public static class Profile progress.Report(14); // Decompile AM2RWrapper.apk - CrossPlatformOperations.RunJavaJar("\"" + apktoolPath + "\" d \"" + dataPath + "/android/AM2RWrapper.apk\"", tempDir); + CrossPlatformOperations.RunJavaJar($"\"{apktoolPath}\" d \"{dataPath}/android/AM2RWrapper.apk\"", tempDir); log.Info("AM2RWrapper decompiled."); progress.Report(28); // Add datafiles: 1.1, new datafiles, hq music, am2r.ini - string workingDir = tempDir + "/AM2RWrapper/assets"; + string workingDir = $"{tempDir}/AM2RWrapper/assets"; ZipFile.ExtractToDirectory(Core.AM2R11File, workingDir); - HelperMethods.DirectoryCopy(dataPath + "/files_to_copy", workingDir); + HelperMethods.DirectoryCopy($"{dataPath}/files_to_copy", workingDir); if (useHqMusic) - HelperMethods.DirectoryCopy(Core.PatchDataPath + "/data/HDR_HQ_in-game_music", workingDir); + HelperMethods.DirectoryCopy($"{Core.PatchDataPath}/data/HDR_HQ_in-game_music", workingDir); // Yes, I'm aware this is dumb. If you've got any better ideas for how to copy a seemingly randomly named .ini from this folder to the APK, please let me know. foreach (FileInfo file in new DirectoryInfo(dataPath).GetFiles().Where(f => f.Name.EndsWith("ini"))) - File.Copy(file.FullName, workingDir + "/" + file.Name); + File.Copy(file.FullName, $"{workingDir}/{file.Name}"); log.Info("AM2R_11.zip extracted and datafiles copied into AM2RWrapper."); progress.Report(42); // Patch data.win to game.droid - CrossPlatformOperations.ApplyXdeltaPatch(workingDir + "/data.win", dataPath + "/droid.xdelta", workingDir + "/game.droid"); + CrossPlatformOperations.ApplyXdeltaPatch($"{workingDir}/data.win", $"{dataPath}/droid.xdelta", $"{workingDir}/game.droid"); log.Info("game.droid successfully patched."); progress.Report(56); // Delete unnecessary files - File.Delete(workingDir + "/AM2R.exe"); - File.Delete(workingDir + "/D3DX9_43.dll"); - File.Delete(workingDir + "/explanations.txt"); - File.Delete(workingDir + "/modifiers.ini"); - File.Delete(workingDir + "/readme.txt"); - File.Delete(workingDir + "/data.win"); - Directory.Delete(workingDir + "/mods", true); - Directory.Delete(workingDir + "/lang/headers", true); - if (OS.IsLinux) File.Delete(workingDir + "/icon.png"); + File.Delete($"{workingDir}/AM2R.exe"); + File.Delete($"{workingDir}/D3DX9_43.dll"); + File.Delete($"{workingDir}/explanations.txt"); + File.Delete($"{workingDir}/modifiers.ini"); + File.Delete($"{workingDir}/readme.txt"); + File.Delete($"{workingDir}/data.win"); + Directory.Delete($"{workingDir}/mods", true); + Directory.Delete($"{workingDir}/lang/headers", true); + if (OS.IsLinux) File.Delete($"{workingDir}/icon.png"); // Modify apktool.yml to NOT compress ogg files - string apktoolText = File.ReadAllText(workingDir + "/../apktool.yml"); + string apktoolText = File.ReadAllText($"{workingDir}/../apktool.yml"); apktoolText = apktoolText.Replace("doNotCompress:", "doNotCompress:\n- ogg"); - File.WriteAllText(workingDir + "/../apktool.yml", apktoolText); + File.WriteAllText($"{workingDir}/../apktool.yml", apktoolText); log.Info("Unnecessary files removed, apktool.yml modified to prevent ogg compression."); progress.Report(70); // Rebuild APK - CrossPlatformOperations.RunJavaJar("\"" + apktoolPath + "\" b AM2RWrapper -o \"" + profile.Name + ".apk\"", tempDir); - log.Info("AM2RWrapper rebuilt into " + profile.Name + ".apk."); + CrossPlatformOperations.RunJavaJar($"\"{apktoolPath}\" b AM2RWrapper -o \"{profile.Name}.apk\"", tempDir); + log.Info($"AM2RWrapper rebuilt into {profile.Name}.apk."); progress.Report(84); // Debug-sign APK - CrossPlatformOperations.RunJavaJar("\"" + uberPath + "\" -a \"" + profile.Name + ".apk\"", tempDir); + CrossPlatformOperations.RunJavaJar($"\"{uberPath}\" -a \"{profile.Name}.apk\"", tempDir); // Extra file cleanup - File.Copy(tempDir + "/" + profile.Name + "-aligned-debugSigned.apk", CrossPlatformOperations.CurrentPath + "/" + profile.Name + ".apk", true); - log.Info(profile.Name + ".apk signed and moved to " + CrossPlatformOperations.CurrentPath + "/" + profile.Name + ".apk."); + File.Copy($"{tempDir}/{profile.Name}-aligned-debugSigned.apk", $"{CrossPlatformOperations.CurrentPath}/{profile.Name}.apk", true); + log.Info($"{profile.Name}.apk signed and moved to {CrossPlatformOperations.CurrentPath}/{profile.Name}.apk."); HelperMethods.DeleteDirectory(tempDir); // Done progress.Report(100); - log.Info("Successfully created Android APK for profile " + profile.Name + "."); - CrossPlatformOperations.OpenFolderAndSelectFile(CrossPlatformOperations.CurrentPath + "/" + profile.Name + ".apk"); + log.Info($"Successfully created Android APK for profile {profile.Name}."); + CrossPlatformOperations.OpenFolderAndSelectFile($"{CrossPlatformOperations.CurrentPath}/{profile.Name}.apk"); } /// @@ -641,10 +640,10 @@ public static class Profile // These are used on both windows and linux for game logging string savePath = OS.IsWindows ? profile.SaveLocation.Replace("%localappdata%", Environment.GetEnvironmentVariable("LOCALAPPDATA")) : profile.SaveLocation.Replace("~", CrossPlatformOperations.Home); - DirectoryInfo logDir = new DirectoryInfo(savePath + "/logs"); + DirectoryInfo logDir = new DirectoryInfo($"{savePath}/logs"); string date = String.Join("-", DateTime.Now.ToString().Split(Path.GetInvalidFileNameChars(), StringSplitOptions.RemoveEmptyEntries)); - log.Info("Launching game profile " + profile.Name + "."); + log.Info($"Launching game profile {profile.Name}."); if (OS.IsWindows) { // Sets the arguments to empty, or to the profiles save path/logs and create time based logs. Creates the folder if necessary. @@ -653,17 +652,17 @@ public static class Profile // Game logging if (useLogging) { - log.Info("Performing logging setup for profile " + profile.Name + "."); + log.Info($"Performing logging setup for profile {profile.Name}."); if (!Directory.Exists(logDir.FullName)) Directory.CreateDirectory(logDir.FullName); - if (File.Exists(logDir.FullName + "/" + profile.Name + ".txt")) - HelperMethods.RecursiveRollover(logDir.FullName + "/" + profile.Name + ".txt", 5); + if (File.Exists($"{logDir.FullName}/{profile.Name}.txt")) + HelperMethods.RecursiveRollover($"{logDir.FullName}/{profile.Name}.txt", 5); - StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt"); + StreamWriter stream = File.AppendText($"{logDir.FullName}/{profile.Name}.txt"); - stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date); + stream.WriteLine($"AM2RLauncher {Core.Version} log generated at {date}"); if (Core.IsThisRunningFromWine) stream.WriteLine("Using WINE!"); @@ -672,16 +671,16 @@ public static class Profile stream.Close(); - arguments = "-debugoutput \"" + logDir.FullName + "/" + profile.Name + ".txt\" -output \"" + logDir.FullName + "/" + profile.Name + ".txt\""; + arguments = $"-debugoutput \"{logDir.FullName}/{profile.Name}.txt\" -output \"{logDir.FullName}/{profile.Name}.txt\""; } ProcessStartInfo proc = new ProcessStartInfo(); - proc.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name; - proc.FileName = proc.WorkingDirectory + "/AM2R.exe"; + proc.WorkingDirectory = $"{Core.ProfilesPath}/{profile.Name}"; + proc.FileName = $"{proc.WorkingDirectory}/AM2R.exe"; proc.Arguments = arguments; - log.Info("CWD of Profile is " + proc.WorkingDirectory); + log.Info($"CWD of Profile is {proc.WorkingDirectory}"); using Process p = Process.Start(proc); Core.SetForegroundWindow(p.MainWindowHandle); @@ -691,7 +690,7 @@ public static class Profile { ProcessStartInfo startInfo = new ProcessStartInfo(); - log.Info("User does " + (String.IsNullOrWhiteSpace(envVars) ? "not" : "") + " have custom environment variables set."); + log.Info($"User does {(String.IsNullOrWhiteSpace(envVars) ? "not" : "")} have custom environment variables set."); //TODO: make this more readable at one day if (!String.IsNullOrWhiteSpace(envVars)) @@ -700,7 +699,7 @@ public static class Profile { // Env var variable string variable = envVars.Substring(0, envVars.IndexOf('=')); - envVars = envVars.Replace(variable + "=", ""); + envVars = envVars.Replace($"{variable}=", ""); // This thing here is the value parser. Since values are sometimes in quotes, i need to compensate for them. int valueSubstringLength; @@ -723,7 +722,7 @@ public static class Profile string value = envVars.Substring(0, valueSubstringLength); envVars = envVars.Substring(value.Length); - log.Info("Adding user variable \"" + variable + "\" with value \"" + value + "\""); + log.Info($"Adding user variable \"{variable}\" with value \"{value}\""); startInfo.EnvironmentVariables[variable] = value; } } @@ -732,15 +731,15 @@ public static class Profile string terminalOutput = null; startInfo.UseShellExecute = false; - startInfo.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name; - startInfo.FileName = startInfo.WorkingDirectory + "/AM2R.AppImage"; + startInfo.WorkingDirectory = $"{Core.ProfilesPath}/{profile.Name}"; + startInfo.FileName = $"{startInfo.WorkingDirectory}/AM2R.AppImage"; - log.Info("CWD of Profile is " + startInfo.WorkingDirectory); + log.Info($"CWD of Profile is {startInfo.WorkingDirectory}"); log.Debug("Launching game with following variables: "); foreach (System.Collections.DictionaryEntry item in startInfo.EnvironmentVariables) { - log.Debug("Key: \"" + item.Key + "\" Value: \"" + item.Value + "\""); + log.Debug($"Key: \"{item.Key}\" Value: \"{item.Value}\""); } using (Process p = new Process()) @@ -749,10 +748,10 @@ public static class Profile if (useLogging) { p.StartInfo.RedirectStandardOutput = true; - p.OutputDataReceived += (_, e) => { terminalOutput += e.Data + "\n"; }; + p.OutputDataReceived += (_, e) => { terminalOutput += $"{e.Data}\n"; }; p.StartInfo.RedirectStandardError = true; - p.ErrorDataReceived += (_, e) => { terminalOutput += e.Data + "\n"; }; + p.ErrorDataReceived += (_, e) => { terminalOutput += $"{e.Data}\n"; }; } p.Start(); @@ -768,18 +767,18 @@ public static class Profile if (terminalOutput != null) { - log.Info("Performed logging setup for profile " + profile.Name + "."); + log.Info($"Performed logging setup for profile {profile.Name}."); if (!Directory.Exists(logDir.FullName)) Directory.CreateDirectory(logDir.FullName); - if (File.Exists(logDir.FullName + "/" + profile.Name + ".txt")) - HelperMethods.RecursiveRollover(logDir.FullName + "/" + profile.Name + ".txt", 5); + if (File.Exists($"{logDir.FullName}/{profile.Name}.txt")) + HelperMethods.RecursiveRollover($"{logDir.FullName}/{profile.Name}.txt", 5); - StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt"); + StreamWriter stream = File.AppendText($"{logDir.FullName}/{profile.Name}.txt"); // Write general info - stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date); + stream.WriteLine($"AM2RLauncher {Core.Version} log generated at {date}"); // Write what was in the terminal stream.WriteLine(terminalOutput); @@ -798,40 +797,40 @@ public static class Profile // Game logging if (useLogging) { - log.Info("Performing logging setup for profile " + profile.Name + "."); + log.Info($"Performing logging setup for profile {profile.Name}."); if (!Directory.Exists(logDir.FullName)) Directory.CreateDirectory(logDir.FullName); - if (File.Exists(logDir.FullName + "/" + profile.Name + ".txt")) - HelperMethods.RecursiveRollover(logDir.FullName + "/" + profile.Name + ".txt", 5); + if (File.Exists($"{logDir.FullName}/{profile.Name}.txt")) + HelperMethods.RecursiveRollover($"{logDir.FullName}/{profile.Name}.txt", 5); - StreamWriter stream = File.AppendText(logDir.FullName + "/" + profile.Name + ".txt"); + StreamWriter stream = File.AppendText($"{logDir.FullName}/{profile.Name}.txt"); - stream.WriteLine("AM2RLauncher " + Core.Version + " log generated at " + date); + stream.WriteLine($"AM2RLauncher {Core.Version} log generated at {date}"); stream.Flush(); stream.Close(); - arguments += " --stdout \"" + logDir.FullName + "/" + profile.Name + ".txt\" --stderr \"" + logDir.FullName + "/" + profile.Name + ".txt\""; + arguments += $" --stdout \"{logDir.FullName}/{profile.Name}.txt\" --stderr \"{logDir.FullName}/{profile.Name}.txt\""; } ProcessStartInfo proc = new ProcessStartInfo(); - proc.WorkingDirectory = Core.ProfilesPath + "/" + profile.Name; + proc.WorkingDirectory = $"{Core.ProfilesPath}/{profile.Name}"; proc.FileName = "open"; proc.Arguments = arguments; - log.Info("CWD of Profile is " + proc.WorkingDirectory); + log.Info($"CWD of Profile is {proc.WorkingDirectory}"); using Process p = Process.Start(proc); p?.WaitForExit(); } else - log.Error(OS.Name + " cannot run games!"); + log.Error($"{OS.Name} cannot run games!"); - log.Info("Profile " + profile.Name + " process exited."); + log.Info($"Profile {profile.Name} process exited."); } /// @@ -841,6 +840,6 @@ public static class Profile public static bool IsPatchDataCloned() { // isValid seems to only check for a .git folder, and there are cases where that exists, but not the profile.xml - return File.Exists(Core.PatchDataPath + "/profile.xml") && Repository.IsValid(Core.PatchDataPath); + return File.Exists($"{Core.PatchDataPath}/profile.xml") && Repository.IsValid(Core.PatchDataPath); } } \ No newline at end of file