installer update bump

This commit is contained in:
CWX 2022-05-19 14:41:44 +01:00
parent 59ffbddf3b
commit e8934029ae
16 changed files with 250 additions and 308 deletions

View File

@ -1,97 +1,81 @@
using System.IO;
using System;
using System.Diagnostics;
using System.Threading;
using Spectre.Console;
using SPT_AKI_Installer.Aki.Helper;
using Spectre.Console;
using System;
using System.IO;
namespace SPT_AKI_Installer.Aki.Core
{
//TODO:
// delete patcher zip and aki zip
// locales, language selection
// PreCheckHelper.AkiCheck is currently hardcoded for 2.3.1
// get waffle to add exit code on patcher
// remove all user input other than errors
//comments:
// static: FileHelper, ZipHelper, LogHelper
// nonStatic: ProcessHelper, PreCheckHelper, StringHelper
// make the installer download relevant version of patcher and aki based on game version if possible
public static class SPTinstaller
{
static void Main(string[] args)
static void Main()
{
SpectreHelper spectreHelper = new SpectreHelper();
spectreHelper.Figlet("SPT-AKI INSTALLER");
string targetPath = Environment.CurrentDirectory;
PreCheckHelper preCheckHelper = new();
//#if DEBUG
#if DEBUG
targetPath = @"D:\install";
//#endif
preCheckHelper.GameCheck(out string gamePath);
#endif
SpectreHelper.Figlet("SPT-AKI INSTALLER", Color.Yellow);
PreCheckHelper.GameCheck(out string originalGamePath);
if (preCheckHelper.PatcherCheck(gamePath,targetPath, out string patchRef))
if (originalGamePath == targetPath)
{
LogHelper.Info($"Correct Zip for Patcher Present: {patchRef}");
}
else
{
LogHelper.Error("Patcher zip is Incorrect or missing");
LogHelper.Error("Press enter to close the app");
Console.ReadKey();
Environment.Exit(0);
CloseApp("Installer is located in EFT's original directory! \n Please move the installer to a seperate folder as per the guide!");
}
if (preCheckHelper.AkiCheck(targetPath,out string akiRef))
var checkForExistingFiles = FileHelper.FindFile(targetPath, "EscapeFromTarkov.exe");
//Console.WriteLine(checkForExistingFiles ?? "null");
if (checkForExistingFiles != null)
{
LogHelper.Info($"Correct Zip for SPT-AKI Present: {akiRef}");
CloseApp("Installer is located in a Folder that has existing Game Files \n Please make sure the installer is in a fresh folder as per the guide");
}
else
//Console.ReadKey();
PreCheckHelper.PatcherZipCheck(originalGamePath, targetPath, out string patcherZipPath);
PreCheckHelper.AkiZipCheck(targetPath, out string akiZipPath);
if (patcherZipPath == null && PreCheckHelper.PatcherNeededCheck())
{
LogHelper.Error("SPT-AKI zip is Incorrect or missing");
LogHelper.Error("Press enter to close the app");
Console.ReadKey();
Environment.Exit(0);
CloseApp("Game Version needs to be patched to match Aki Version \n but Patcher is missing or the wrong version \n Press enter to close the app");
}
// checks for input to copy game files
LogHelper.User("PLEASE PRESS ENTER TO COPY GAME FILES!");
Console.ReadKey();
GameCopy(gamePath, targetPath,patchRef, akiRef);
if (akiZipPath == null)
{
CloseApp("Aki's Zip could not be found \n Press enter to close the app");
}
/// <summary>
/// copies and pastes EFT to AKI installer test folder
/// </summary>
/// <param name="gamePath"></param>
/// <param name="targetPath"></param>
static void GameCopy(string gamePath, string targetPath, string patchRef, string akiRef)
if (PreCheckHelper.PatcherNeededCheck() && !PreCheckHelper.PatcherAkiCheck())
{
//#if !DEBUG
FileHelper.CopyDirectory(gamePath, targetPath, true);
//#endif
LogHelper.User("GAME HAS BEEN COPIED, PRESS ENTER TO EXTRACT PATCHER!");
Console.ReadKey();
PatcherCopy(gamePath, targetPath,patchRef, akiRef);
CloseApp("Patcher does not match downgraded version that Aki Requires \n Press enter to close the app");
}
/// <summary>
/// extracts patcher and moves out inner folders
/// </summary>
/// <param name="gamePath"></param>
/// <param name="targetPath"></param>
/// <param name="patchRef"></param>
/// <param name="akiRef"></param>
static void PatcherCopy(string gamePath, string targetPath, string patchRef, string akiRef)
LogHelper.Info("Copying game files");
GameCopy(originalGamePath, targetPath);
if (PreCheckHelper.PatcherNeededCheck())
{
//#if !DEBUG
ZipHelper.Decompress(patchRef, targetPath);
FileHelper.FindFolder(patchRef, targetPath, out DirectoryInfo dir);
PatcherCopy(targetPath, patcherZipPath);
PatcherProcess(targetPath);
}
AkiInstall(targetPath, akiZipPath);
DeleteZip(patcherZipPath, akiZipPath);
}
static void GameCopy(string originalGamePath, string targetPath)
{
FileHelper.CopyDirectory(originalGamePath, targetPath, true);
LogHelper.Info("Game has been copied, Extracting patcher");
}
static void PatcherCopy(string targetPath, string patcherZipPath)
{
ZipHelper.Decompress(patcherZipPath, targetPath);
FileHelper.FindFolder(patcherZipPath, targetPath, out DirectoryInfo dir);
FileHelper.CopyDirectory(dir.FullName, targetPath, true);
if (dir.Exists)
{
dir.Delete(true);
@ -102,47 +86,39 @@ namespace SPT_AKI_Installer.Aki.Core
LogHelper.Error($"please delete folder called {dir.FullName}");
}
}
//#endif
PatcherProcessStart(targetPath, akiRef);
}
/// <summary>
/// starts patcher and checks for user input to exit patcher and proceed
/// </summary>
/// <param name="targetPath"></param>
/// <param name="akiRef"></param>
static void PatcherProcessStart(string targetPath, string akiRef)
static void PatcherProcess(string targetPath)
{
//#if !DEBUG
LogHelper.Info("PATCHER HAS BEEN EXTRACTED, STARTING PATCHER!");
LogHelper.Info("patcher has been extracted, starting patcher");
ProcessHelper patcherProcess = new();
patcherProcess.StartProcess(Path.Join(targetPath + "/patcher.exe"), targetPath);
//#endif
LogHelper.User("PATCHER HAS BEEN STARTED, TYPE YES ONCE THE PATCHER IS COMPLETE!");
var complete = Console.ReadLine();
// waiting for user to enter "yes", if something else is entered do while loop
while (!string.Equals(complete, "yes", StringComparison.OrdinalIgnoreCase))
{
LogHelper.Warning("YOU DIDNT TYPE YES, IF SOMETHING WENT WRONG MAKE A SUPPORT THREAD AND CLOSE THIS APP");
LogHelper.User("IF IT DID FINISH TYPE YES NOW");
complete = Console.ReadLine();
FileHelper.DeleteFiles(Path.Join(targetPath, "/patcher.exe"));
}
// if user input "yes" kill patcher process, delete patcher.exe, extract aki zip
if (string.Equals(complete, "yes", StringComparison.OrdinalIgnoreCase))
static void AkiInstall(string targetPath, string akiZipPath)
{
//#if !DEBUG
patcherProcess.EndProcess();
Thread.Sleep(1000);
FileHelper.DeleteFile("file", targetPath + "/patcher.exe");
ZipHelper.Decompress(akiRef, targetPath);
//#endif
LogHelper.Info("AKI HAS BEEN EXTRACTED, RUN THE SERVER AND WAIT TILL YOU SEE HAPPY SERVER THEN LAUNCHER AND ENJOY!");
LogHelper.User("PRESS ENTER TO CLOSE THE APP");
ZipHelper.Decompress(akiZipPath, targetPath);
LogHelper.Info("Aki has been extracted");
}
static void DeleteZip(string patcherZipPath, string akiZipPath)
{
FileHelper.DeleteFiles(patcherZipPath, false);
FileHelper.DeleteFiles(akiZipPath, false);
LogHelper.User("Removed Zips, Press enter to close the installer, you can then delete the installer");
LogHelper.User("ENJOY SPT-AKI!");
Console.ReadKey();
Environment.Exit(0);
}
static void CloseApp(string text)
{
LogHelper.Warning(text);
Console.ReadKey();
Environment.Exit(0);
}
}
}
}

View File

@ -1,143 +1,50 @@
using System;
using System.IO;
using Spectre.Console;
using System.Threading;
namespace SPT_AKI_Installer.Aki.Helper
{
public static class FileHelper
{
public static int totalFiles;
/// <summary>
/// CopyDirectory will use old path and copy to new path and
/// asks if inner files/folders should be included
/// </summary>
/// <exception cref="DirectoryNotFoundException"></exception>
public static void CopyDirectory(string oldDir, string newDir, bool recursive)
public static void CopyDirectory(string oldDir, string newDir, bool overwrite)
{
int totalFiles = Directory.GetFiles(oldDir, "*.*", SearchOption.AllDirectories).Length;
AnsiConsole.Progress().Columns(
new PercentageColumn(),
new TaskDescriptionColumn(),
new SpinnerColumn(),
new ElapsedTimeColumn()
new ProgressBarColumn(),
new ElapsedTimeColumn(),
new SpinnerColumn()
).Start((ProgressContext context) =>
{
var dir = new DirectoryInfo(oldDir);
var task = context.AddTask("Copying Files", true, totalFiles);
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
DirectoryInfo[] dirs = dir.GetDirectories();
foreach (FileInfo f in dir.GetFiles())
foreach (string dirPath in Directory.GetDirectories(oldDir, "*", SearchOption.AllDirectories))
{
totalFiles++;
}
foreach (DirectoryInfo subD in dirs)
{
foreach (FileInfo f in subD.GetFiles())
{
totalFiles++;
}
Directory.CreateDirectory(dirPath.Replace(oldDir, newDir));
}
var task = context.AddTask("Copying files: ", true, totalFiles);
Directory.CreateDirectory(newDir);
foreach (FileInfo file in dir.GetFiles())
foreach (string newPath in Directory.GetFiles(oldDir, "*.*", SearchOption.AllDirectories))
{
string targetFilePath = Path.Combine(newDir, file.Name);
file.CopyTo(targetFilePath, true);
}
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
{
string newDestinationDir = Path.Combine(newDir, subDir.Name);
AltCopyDirectory(subDir.FullName, newDestinationDir, true);
}
File.Copy(newPath, newPath.Replace(oldDir, newDir), overwrite);
task.Increment(1);
}
});
//var dir = new DirectoryInfo(oldDir);
//if (!dir.Exists)
// throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
//DirectoryInfo[] dirs = dir.GetDirectories();
//Directory.CreateDirectory(newDir);
//foreach (FileInfo file in dir.GetFiles())
//{
// string targetFilePath = Path.Combine(newDir, file.Name);
// file.CopyTo(targetFilePath, true);
//}
//if (recursive)
//{
// foreach (DirectoryInfo subDir in dirs)
// {
// string newDestinationDir = Path.Combine(newDir, subDir.Name);
// CopyDirectory(subDir.FullName, newDestinationDir, true);
// }
//}
}
public static void AltCopyDirectory(string oldDir, string newDir, bool recursive)
public static void DeleteFiles(string filePath, bool allFolders = false)
{
var dir = new DirectoryInfo(oldDir);
if (!dir.Exists)
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
DirectoryInfo[] dirs = dir.GetDirectories();
Directory.CreateDirectory(newDir);
foreach (FileInfo file in dir.GetFiles())
{
string targetFilePath = Path.Combine(newDir, file.Name);
file.CopyTo(targetFilePath, true);
}
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
{
string newDestinationDir = Path.Combine(newDir, subDir.Name);
AltCopyDirectory(subDir.FullName, newDestinationDir, true);
}
}
}
/// <summary>
/// DeleteFiles will use a type to look for, the path
/// and if all inner files/folders should be included
/// </summary>
/// <remarks>
/// Types are "file" or "folder" as a string
/// </remarks>
public static void DeleteFile(string type, string filePath, bool allFolders = false)
{
// type = "file" or "folder"
if (string.Equals(type, "file", StringComparison.OrdinalIgnoreCase))
if (filePath.Contains('.'))
{
File.Delete(filePath);
}
if (string.Equals(type, "folder", StringComparison.OrdinalIgnoreCase))
else
{
Directory.Delete(filePath, allFolders);
}
}
/// <summary>
/// finds file based on Path and File name
/// </summary>
/// <param name="path"></param>
/// <param name="name"></param>
/// <returns>String or null</returns>
public static string FindFile(string path, string name)
{
string[] filePaths = Directory.GetFiles(path);
@ -151,12 +58,20 @@ namespace SPT_AKI_Installer.Aki.Helper
return null;
}
/// <summary>
/// Finds folder with name supplied, out = directory for extracted patch folder
/// </summary>
/// <param name="patchRef"></param>
/// <param name="dir"></param>
/// <returns>bool</returns>
public static string FindFile(string path, string name, string altName)
{
string[] filePaths = Directory.GetFiles(path);
foreach (string file in filePaths)
{
if (file.Contains(name, StringComparison.OrdinalIgnoreCase) &&
file.Contains(altName, StringComparison.OrdinalIgnoreCase))
{
return file;
}
}
return null;
}
public static bool FindFolder(string patchRef, string targetPath, out DirectoryInfo dir)
{
var patchInfo = new FileInfo(patchRef);

View File

@ -1,5 +1,4 @@
using System;
using Spectre.Console;
using Spectre.Console;
namespace SPT_AKI_Installer.Aki.Helper
{

View File

@ -6,15 +6,16 @@ using System.Diagnostics;
namespace SPT_AKI_Installer.Aki.Helper
{
public class PreCheckHelper
public static class PreCheckHelper
{
private const string registryInstall = @"Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\EscapeFromTarkov";
private static string gameVersion;
private static string patchZip;
private static string patchToVersion;
private static string akiZip;
private static string akiVersion;
/// <summary>
/// gets the original EFT game path
/// </summary>
/// <returns>Path or null</returns>
public string DetectOriginalGamePath()
public static string DetectOriginalGamePath()
{
// We can't detect the installed path on non-Windows
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
@ -26,11 +27,7 @@ namespace SPT_AKI_Installer.Aki.Helper
return info?.DirectoryName;
}
/// <summary>
/// checks path is not null, out = gamePath
/// </summary>
/// <param name="gamePath"></param>
public void GameCheck(out string gamePath)
public static void GameCheck(out string gamePath)
{
string Path = DetectOriginalGamePath();
@ -44,48 +41,39 @@ namespace SPT_AKI_Installer.Aki.Helper
gamePath = Path;
}
/// <summary>
/// Checks version of EFT installed, Then checks that matches the Zip, out = patch version number 0.12.12.*here*
/// </summary>
/// <param name="gamePath"></param>
/// <param name="targetPath"></param>
/// <param name="patchRef"></param>
/// <returns>bool</returns>
public bool PatcherCheck(string gamePath,string targetPath, out string patchRef)
public static void PatcherZipCheck(string gamePath, string targetPath, out string patcherZipPath)
{
StringHelper stringHelper = new StringHelper();
FileVersionInfo version = FileVersionInfo.GetVersionInfo(Path.Join(gamePath + "/EscapeFromTarkov.exe"));
string versionCheck = stringHelper.Splitter(version.ProductVersion, '-', '.', 2);
LogHelper.Info($"GAME VERSION IS: {version.ProductVersion}");
string patcherRef = FileHelper.FindFile(targetPath, versionCheck);
if (patcherRef != null)
{
patchRef = patcherRef;
return true;
// example patch name - Patcher.12.12.15.17861.to.12.12.15.17349.zip
gameVersion = FileVersionInfo.GetVersionInfo(Path.Join(gamePath + "/EscapeFromTarkov.exe")).ProductVersion.Replace('-', '.').Split('.')[^2];
patchZip = FileHelper.FindFile(targetPath, gameVersion, "Patcher");
patchToVersion = patchZip?.Split('.')[^2];
patcherZipPath = patchZip;
}
patchRef = null;
return false;
public static void AkiZipCheck(string targetPath, out string akiZipPath)
{
// example aki name - RELEASE-SPT-2.3.1-17349.zip
akiZip = FileHelper.FindFile(targetPath, "SPT", "RELEASE");
akiVersion = akiZip?.Replace('-', '.').Split('.')[^2];
akiZipPath = akiZip;
}
/// <summary>
/// Checks Aki Zip is 2.3.1 currently
/// will return true if Patcher version at the end of the zip matches aki zip version
/// </summary>
/// <param name="targetPath"></param>
/// <param name="akiRef"></param>
/// <returns>bool</returns>
public bool AkiCheck(string targetPath,out string akiRef)
public static bool PatcherAkiCheck()
{
string aki = FileHelper.FindFile(targetPath, "2.3.1");
if (aki != null)
{
akiRef = aki;
return true;
return patchToVersion == akiVersion;
}
akiRef = null;
return false;
/// <summary>
/// will return true if game version is not equal to aki zip version (patcher is needed)
/// </summary>
/// <returns>bool</returns>
public static bool PatcherNeededCheck()
{
return gameVersion != akiVersion;
}
}
}

View File

@ -1,29 +1,105 @@
using System.Diagnostics;
using System.Threading;
using System;
namespace SPT_AKI_Installer.Aki.Helper
{
public class ProcessHelper
{
private Process _process;
private string _exeDir;
private string _workingDir;
/// <summary>
/// Starts process with path and file name including include .exe,
/// sets working directory too
/// </summary>
public void StartProcess(string exeDir, string workingDir)
{
_exeDir = exeDir;
_workingDir = workingDir;
_process = new Process();
_process.StartInfo.FileName = exeDir;
_process.StartInfo.WorkingDirectory = workingDir;
_process.EnableRaisingEvents = true;
_process.StartInfo.Arguments = "autoclose";
_process.Start();
_process.WaitForExit();
ExitCodeCheck(_process.ExitCode);
}
/// <summary>
/// Kills the Process
/// </summary>
public void EndProcess()
public void ExitCodeCheck(int exitCode)
{
_process.Kill();
/*
public enum PatcherExitCode
{
ProgramClosed = 0,
Success = 10,
EftExeNotFound = 11,
NoPatchFolder = 12,
MissingFile = 13,
MissingDir = 14
}
*/
switch (exitCode)
{
case 0:
LogHelper.Warning("Patcher was closed before completing!");
LogHelper.Warning("If you need to start the patcher again, type RETRY");
LogHelper.Warning("If you want to close the installer, type CLOSE");
var response = Console.ReadLine();
while (!string.Equals(response, "retry", StringComparison.OrdinalIgnoreCase) ||
!string.Equals(response, "close", StringComparison.OrdinalIgnoreCase))
{
LogHelper.Warning("answer needs to be retry or close");
LogHelper.Warning("Try Again!");
}
if (string.Equals(response, "retry", StringComparison.OrdinalIgnoreCase))
{
StartProcess(_exeDir, _workingDir);
break;
}
if (string.Equals(response, "close", StringComparison.OrdinalIgnoreCase))
{
Environment.Exit(0);
break;
}
break;
case 10:
LogHelper.User("Patcher Finished Successfully, extracting Aki");
break;
case 11:
LogHelper.Error("EscapeFromTarkov.exe is missing from the install Path");
LogHelper.Warning("Check your game files in their original location are complete!");
LogHelper.Warning("Closing the installer in 20 seconds");
Thread.Sleep(20000);
Environment.Exit(0);
break;
case 12:
LogHelper.Error("Patchers Folder called 'Aki_Patches' missing");
LogHelper.Warning("Closing the installer in 20 seconds");
Thread.Sleep(20000);
Environment.Exit(0);
break;
case 13:
LogHelper.Error("EFT files was missing a Vital file to continue");
LogHelper.Warning("please reinstall EFT through the BSG launcher");
LogHelper.Warning("Closing the installer in 20 seconds");
Thread.Sleep(20000);
Environment.Exit(0);
break;
case 14:
LogHelper.Error("Patcher Reported Missing Folder");
// check with Waffle what this one is
LogHelper.Warning("Closing the installer in 20 seconds");
Thread.Sleep(20000);
Environment.Exit(0);
break;
}
}
}
}

View File

@ -1,20 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Spectre.Console;
using Spectre.Console;
namespace SPT_AKI_Installer.Aki.Helper
{
public class SpectreHelper
public static class SpectreHelper
{
public void Figlet(string text)
public static void Figlet(string text, Color color)
{
AnsiConsole.Write(
new FigletText(text)
.Centered()
.Color(Color.Yellow));
.Color(color));
}
}
}

View File

@ -1,18 +0,0 @@
namespace SPT_AKI_Installer.Aki.Helper
{
public class StringHelper
{
/// <summary>
/// string to split, changes oldChar to newChar
/// </summary>
/// <param name="toSplit"></param>
/// <param name="oldChar"></param>
/// <param name="newChar"></param>
/// <param name="amount"></param>
/// <returns>returns the string at a position using amount</returns>
public string Splitter(string toSplit, char oldChar, char newChar, int amount)
{
return toSplit.Replace(oldChar, newChar).Split(newChar)[^amount];
}
}
}

View File

@ -8,22 +8,19 @@ namespace SPT_AKI_Installer.Aki.Helper
{
public static class ZipHelper
{
/// <summary>
/// will extract Zips in LZMA compression format, using Zips path
/// to new path
/// </summary>
public static void Decompress(string ArchivePath, string OutputFolderPath)
{
AnsiConsole.Progress().Columns(
new PercentageColumn(),
new TaskDescriptionColumn(),
new ProgressBarColumn(),
new ElapsedTimeColumn()
new ElapsedTimeColumn(),
new SpinnerColumn()
).Start((ProgressContext context) =>
{
using var archive = ZipArchive.Open(ArchivePath);
var entries = archive.Entries.Where(entry => !entry.IsDirectory);
var task = context.AddTask("Extracting", true, entries.Count());
var task = context.AddTask("Extracting Files", true, entries.Count());
foreach (var entry in entries)
{

3
Aki.Locales/CN.json Normal file
View File

@ -0,0 +1,3 @@
{
}

3
Aki.Locales/DE.json Normal file
View File

@ -0,0 +1,3 @@
{
}

3
Aki.Locales/EN.json Normal file
View File

@ -0,0 +1,3 @@
{
}

3
Aki.Locales/FR.json Normal file
View File

@ -0,0 +1,3 @@
{
}

3
Aki.Locales/KR.json Normal file
View File

@ -0,0 +1,3 @@
{
}

3
Aki.Locales/RU.json Normal file
View File

@ -0,0 +1,3 @@
{
}

View File

@ -4,6 +4,6 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project>
<PropertyGroup>
<History>True|2022-05-14T00:56:09.8410037Z;True|2022-05-14T00:54:24.0683990+01:00;True|2022-05-14T00:53:04.7105427+01:00;True|2022-05-14T00:51:00.6280767+01:00;True|2022-05-14T00:49:19.4630888+01:00;True|2022-05-14T00:47:59.2166156+01:00;</History>
<History>True|2022-05-17T00:06:33.6758525Z;True|2022-05-14T01:56:09.8410037+01:00;True|2022-05-14T00:54:24.0683990+01:00;True|2022-05-14T00:53:04.7105427+01:00;True|2022-05-14T00:51:00.6280767+01:00;True|2022-05-14T00:49:19.4630888+01:00;True|2022-05-14T00:47:59.2166156+01:00;</History>
</PropertyGroup>
</Project>

View File

@ -11,10 +11,6 @@
<Content Include="Aki.Asset\icon.ico" />
</ItemGroup>
<ItemGroup>
<Folder Include="Aki.Locales\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.31.0" />
<PackageReference Include="Spectre.Console" Version="0.44.0" />