Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions SpaghettiCh2/InstallTester/App.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
</startup>
</configuration>
39 changes: 39 additions & 0 deletions SpaghettiCh2/InstallTester/InstallTester.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9F48A343-5238-4B71-8F2E-6083FFF2DB6E}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>InstallTester</RootNamespace>
<AssemblyName>InstallTester</AssemblyName>
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
4 changes: 2 additions & 2 deletions SpaghettiCh2/SpaghettiCh2/Models/ScriptContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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)
Expand Down
20 changes: 15 additions & 5 deletions SpaghettiCh2/SpaghettiCh2/ViewModels/InstallationViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<Exception, string>? InstallationError;
public event Action? InstallationSuccess;

Expand Down Expand Up @@ -131,17 +141,17 @@ 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");

OverallProgressMessage = "Installazione in corso...";
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);
Expand Down
2 changes: 1 addition & 1 deletion SpaghettiCh2/SpaghettiCh2/ViewModels/PageViewModelBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace USPInstaller.ViewModels
{
class PageViewModelBase : ObservableObject
public class PageViewModelBase : ObservableObject
{
}
}
188 changes: 188 additions & 0 deletions SpaghettiCh2/USPInstallTester/Program.cs
Original file line number Diff line number Diff line change
@@ -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();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should sanitize the paths that we get - with proper separators for unix systems and windows and with the whitespace trimmed, since we're gonna read this from a config file afterwards and Path.Combine doesn't sanitize path separators

}
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<int> 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;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- https://go.microsoft.com/fwlink/?LinkID=208121. -->
<Project>
<PropertyGroup>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<PublishDir>bin\Release\net8.0\publish\</PublishDir>
<PublishProtocol>FileSystem</PublishProtocol>
<_TargetId>Folder</_TargetId>
<TargetFramework>net8.0</TargetFramework>
<SelfContained>false</SelfContained>
</PropertyGroup>
</Project>
16 changes: 16 additions & 0 deletions SpaghettiCh2/USPInstallTester/USPInstallTester.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\SpaghettiCh2\USPInstaller.csproj" />
</ItemGroup>
<PropertyGroup>
<SatelliteResourceLanguages>en-US;it-IT</SatelliteResourceLanguages>
</PropertyGroup>
</Project>
10 changes: 10 additions & 0 deletions SpaghettiCh2/USPInstaller.sln
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down