diff --git a/SpaghettiCh2/InstallTester/App.config b/SpaghettiCh2/InstallTester/App.config
new file mode 100644
index 0000000..56efbc7
--- /dev/null
+++ b/SpaghettiCh2/InstallTester/App.config
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SpaghettiCh2/InstallTester/InstallTester.csproj b/SpaghettiCh2/InstallTester/InstallTester.csproj
new file mode 100644
index 0000000..82ee32a
--- /dev/null
+++ b/SpaghettiCh2/InstallTester/InstallTester.csproj
@@ -0,0 +1,39 @@
+
+
+
+
+ Debug
+ AnyCPU
+ {9F48A343-5238-4B71-8F2E-6083FFF2DB6E}
+ Exe
+ InstallTester
+ InstallTester
+ v4.7.2
+ 512
+ true
+ true
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+
+
+
+
\ No newline at end of file
diff --git a/SpaghettiCh2/SpaghettiCh2/Models/ScriptContext.cs b/SpaghettiCh2/SpaghettiCh2/Models/ScriptContext.cs
index 157fea1..c5ecb46 100644
--- a/SpaghettiCh2/SpaghettiCh2/Models/ScriptContext.cs
+++ b/SpaghettiCh2/SpaghettiCh2/Models/ScriptContext.cs
@@ -26,7 +26,7 @@ public void ScriptMessage(string message)
public void ScriptError(string error, string title = "Error", bool SetConsoleText = true)
{
- model.Log(title + ": " + error);
+ model.LogError(title + ": " + error);
}
public void UpdateProgressBar(string message, string status, double progressValue, double maxValue)
@@ -45,7 +45,7 @@ public void HideProgressBar()
public bool ScriptQuestion(string message)
{
- return MessageBoxViewModel.Show(message, "Avviso", true).Result;
+ return model.AskUserQuestion(message);
}
public void UpdateProgressValue(double progressValue)
diff --git a/SpaghettiCh2/SpaghettiCh2/ViewModels/InstallationViewModel.cs b/SpaghettiCh2/SpaghettiCh2/ViewModels/InstallationViewModel.cs
index 4f2ef1f..e73b052 100644
--- a/SpaghettiCh2/SpaghettiCh2/ViewModels/InstallationViewModel.cs
+++ b/SpaghettiCh2/SpaghettiCh2/ViewModels/InstallationViewModel.cs
@@ -11,7 +11,7 @@
namespace USPInstaller.ViewModels
{
- partial class InstallationViewModel : PageViewModelBase
+ public partial class InstallationViewModel : PageViewModelBase
{
// HACK: Avalonia wants a public empty constructor so that we can use the designer
// to see how the viewmodel looks at design-time. Not to be used in actual code.
@@ -38,11 +38,21 @@ public void UpdateProgress(string message, string subMessage, double value, doub
ProgressValue = value / maxValue * 100;
}
- public void Log(string s)
+ public virtual void Log(string s)
{
log.AppendLine(s);
}
+ public virtual void LogError(string s)
+ {
+ log.AppendLine(s);
+ }
+
+ public virtual bool AskUserQuestion(string message)
+ {
+ return MessageBoxViewModel.Show(message, "Avviso", true).Result;
+ }
+
public event Action? InstallationError;
public event Action? InstallationSuccess;
@@ -131,9 +141,9 @@ private async Task DumpLog(string log)
}
}
return null;
- }
+ }
- private async Task InstallUndertale(string assetPath, string exePath)
+ public async Task InstallUndertale(string assetPath, string exePath)
{
string scriptPath = Path.Join(assetPath, "Undertale", "installer.csx");
@@ -141,7 +151,7 @@ private async Task InstallUndertale(string assetPath, string exePath)
await RunScriptOn(scriptPath, GetDataFileName(exePath)!);
}
- private async Task InstallDeltarune(string assetPath, string exePath)
+ public async Task InstallDeltarune(string assetPath, string exePath)
{
string scriptsPath = Path.Join(assetPath, "Deltarune", "InstallScripts");
string dataPath = GetDataFileName(exePath)! ?? throw new FileNotFoundException("Non trovo il file di dati del gioco", exePath);
diff --git a/SpaghettiCh2/SpaghettiCh2/ViewModels/PageViewModelBase.cs b/SpaghettiCh2/SpaghettiCh2/ViewModels/PageViewModelBase.cs
index 0ec70ee..3bf543f 100644
--- a/SpaghettiCh2/SpaghettiCh2/ViewModels/PageViewModelBase.cs
+++ b/SpaghettiCh2/SpaghettiCh2/ViewModels/PageViewModelBase.cs
@@ -2,7 +2,7 @@
namespace USPInstaller.ViewModels
{
- class PageViewModelBase : ObservableObject
+ public class PageViewModelBase : ObservableObject
{
}
}
diff --git a/SpaghettiCh2/USPInstallTester/Program.cs b/SpaghettiCh2/USPInstallTester/Program.cs
new file mode 100644
index 0000000..f8757b2
--- /dev/null
+++ b/SpaghettiCh2/USPInstallTester/Program.cs
@@ -0,0 +1,188 @@
+
+using System.ComponentModel;
+using USPInstaller.Models;
+using USPInstaller.ViewModels;
+
+class TestInstallViewModel : InstallationViewModel
+{
+ public TestInstallViewModel() : base()
+ {
+ PropertyChanged += OnPropertyChanged;
+ }
+
+ private void OnPropertyChanged(object? sender, PropertyChangedEventArgs e)
+ {
+ if (e.PropertyName == "OverallProgressMessage")
+ {
+ Console.WriteLine(OverallProgressMessage);
+ }
+ }
+
+ public override bool AskUserQuestion(string message)
+ {
+ // Always assume user selected "yes" to questions
+ return true;
+ }
+
+ public override void LogError(string s)
+ {
+ // Treat any error log as a hard error
+ throw new Exception("Installation script logged an error: rs" + s);
+ }
+}
+
+class Program
+{
+ static string? FindApplicationWithName(string directory, string name)
+ {
+ string attempt = Path.Join(directory, name + ".exe");
+ if (File.Exists(attempt))
+ {
+ return attempt;
+ }
+ attempt = Path.Join(directory, name + ".app");
+ if (Directory.Exists(attempt))
+ {
+ return attempt;
+ }
+ attempt = Path.Join(directory, "run.sh");
+ if (File.Exists(attempt))
+ {
+ return attempt;
+ }
+ return null;
+ }
+
+ static async Task<(string, string)> GetConfig()
+ {
+ string configPath = Path.Join(AppContext.BaseDirectory, "config.txt");
+ if (File.Exists(configPath))
+ {
+ // Read two lines from configPath
+ string[] lines = await File.ReadAllLinesAsync(configPath);
+ if (lines.Length >= 2)
+ {
+ Console.WriteLine("Read configuration from: " + configPath);
+ Console.WriteLine("Assets path: " + lines[0]);
+ Console.WriteLine("Games root path: " + lines[1]);
+ return (lines[0], lines[1]);
+ }
+ }
+ string? assetPath = null;
+ while (assetPath == null)
+ {
+ Console.Write("Asset path: ");
+ assetPath = Console.ReadLine();
+ }
+
+ string? rootDir = null;
+ while (rootDir == null)
+ {
+ Console.Write("Games root directory: ");
+ rootDir = Console.ReadLine();
+ }
+ await File.WriteAllLinesAsync(configPath, [assetPath, rootDir]);
+ Console.WriteLine("Wrote configuration to: " + configPath);
+ return (assetPath, rootDir);
+ }
+
+ // See https://learn.microsoft.com/en-us/dotnet/standard/io/how-to-copy-directories
+ static async Task CopyDirectory(string sourceDir, string destinationDir, bool recursive)
+ {
+ // Get information about the source directory
+ var dir = new DirectoryInfo(sourceDir);
+
+ // Check if the source directory exists
+ if (!dir.Exists)
+ throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
+
+ // Cache directories before we start copying
+ DirectoryInfo[] dirs = dir.GetDirectories();
+
+ // Create the destination directory
+ Directory.CreateDirectory(destinationDir);
+
+ // Get the files in the source directory and copy to the destination directory
+ foreach (FileInfo file in dir.GetFiles())
+ {
+ string targetFilePath = Path.Combine(destinationDir, file.Name);
+ file.CopyTo(targetFilePath);
+ }
+
+ // If recursive and copying subdirectories, recursively call this method
+ if (recursive)
+ {
+ foreach (DirectoryInfo subDir in dirs)
+ {
+ string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
+ await CopyDirectory(subDir.FullName, newDestinationDir, true);
+ }
+ }
+ }
+
+ static async Task CopyToFolder(string directory, string tempPath)
+ {
+ if (Directory.Exists(tempPath))
+ Directory.Delete(tempPath, true);
+ await CopyDirectory(directory, tempPath, true);
+ }
+
+ static async Task Main(string[] args)
+ {
+ (string assetPath, string rootDir) = await GetConfig();
+
+ var patchedRootDir = Path.Combine(rootDir, "Patched");
+ Directory.CreateDirectory(patchedRootDir);
+
+ InstallationViewModel installer = new TestInstallViewModel();
+
+ bool failed = false;
+ foreach (string subDir in Directory.GetDirectories(rootDir))
+ {
+ try
+ {
+ string fileName = Path.GetFileName(subDir);
+ string patchedCopyDir = Path.Combine(patchedRootDir, fileName);
+
+ string? undertaleExe = FindApplicationWithName(subDir, "UNDERTALE");
+ if (undertaleExe != null)
+ {
+ await CopyToFolder(subDir, patchedCopyDir);
+ Console.WriteLine($"\nInstalling Undertale patch on {fileName}...");
+ await installer.InstallUndertale(assetPath, FindApplicationWithName(patchedCopyDir, "UNDERTALE")!);
+ continue;
+ }
+ string? deltaruneExe = FindApplicationWithName(subDir, "DELTARUNE");
+ if (deltaruneExe != null)
+ {
+ await CopyToFolder(subDir, patchedCopyDir);
+ Console.WriteLine($"\nInstalling Deltarune patch on {fileName}...");
+ await installer.InstallDeltarune(assetPath, FindApplicationWithName(patchedCopyDir, "DELTARUNE")!);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Installation to {Path.GetFileName(subDir)} failed:");
+ Console.WriteLine(e.Message);
+ Console.WriteLine(e.StackTrace);
+ failed = true;
+ }
+ }
+
+ if (!failed)
+ {
+ if (!Console.IsOutputRedirected)
+ {
+ Console.WriteLine("\nInstallation completed succesfully :D\nPress any key to exit...");
+ Console.ReadKey();
+ }
+ return 0;
+ }
+ if (!Console.IsOutputRedirected)
+ {
+ Console.WriteLine("\nThere were some errors during installation :(\nPress any key to exit");
+ Console.ReadKey();
+ }
+ return 10;
+ }
+}
\ No newline at end of file
diff --git a/SpaghettiCh2/USPInstallTester/Properties/PublishProfiles/FolderProfile.pubxml b/SpaghettiCh2/USPInstallTester/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..3f4a83a
--- /dev/null
+++ b/SpaghettiCh2/USPInstallTester/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,13 @@
+
+
+
+
+ Release
+ Any CPU
+ bin\Release\net8.0\publish\
+ FileSystem
+ <_TargetId>Folder
+ net8.0
+ false
+
+
\ No newline at end of file
diff --git a/SpaghettiCh2/USPInstallTester/USPInstallTester.csproj b/SpaghettiCh2/USPInstallTester/USPInstallTester.csproj
new file mode 100644
index 0000000..707e631
--- /dev/null
+++ b/SpaghettiCh2/USPInstallTester/USPInstallTester.csproj
@@ -0,0 +1,16 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+ en-US;it-IT
+
+
diff --git a/SpaghettiCh2/USPInstaller.sln b/SpaghettiCh2/USPInstaller.sln
index f25bef3..619cede 100644
--- a/SpaghettiCh2/USPInstaller.sln
+++ b/SpaghettiCh2/USPInstaller.sln
@@ -18,6 +18,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Underanalyzer", "UndertaleM
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UndertaleModLib", "UndertaleModTool\UndertaleModLib\UndertaleModLib.csproj", "{3E1FBADF-4C64-D01C-7F2D-01009E3B0CBB}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "USPInstallTester", "USPInstallTester\USPInstallTester.csproj", "{479C5045-B40D-4978-95EA-E16C9AAFCD94}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +52,14 @@ Global
{3E1FBADF-4C64-D01C-7F2D-01009E3B0CBB}.Release|Any CPU.Build.0 = Release|Any CPU
{3E1FBADF-4C64-D01C-7F2D-01009E3B0CBB}.Release|x64.ActiveCfg = Release|x64
{3E1FBADF-4C64-D01C-7F2D-01009E3B0CBB}.Release|x64.Build.0 = Release|x64
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Debug|x64.ActiveCfg = Debug|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Debug|x64.Build.0 = Debug|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Release|Any CPU.Build.0 = Release|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Release|x64.ActiveCfg = Release|Any CPU
+ {479C5045-B40D-4978-95EA-E16C9AAFCD94}.Release|x64.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE