From 92615d96924506c350853fc975a6433fb5582f4f Mon Sep 17 00:00:00 2001
From: Miepee <38186597+Miepee@users.noreply.github.com>
Date: Thu, 21 Apr 2022 13:15:53 +0200
Subject: [PATCH 1/3] CLI: initial dumping support
---
UndertaleModCli/CommandOptions.cs | 36 +++++++
UndertaleModCli/Program.cs | 163 ++++++++++++++++++++++++++++--
2 files changed, 189 insertions(+), 10 deletions(-)
diff --git a/UndertaleModCli/CommandOptions.cs b/UndertaleModCli/CommandOptions.cs
index 5dd0610af..357c8fab5 100644
--- a/UndertaleModCli/CommandOptions.cs
+++ b/UndertaleModCli/CommandOptions.cs
@@ -79,4 +79,40 @@ public class InfoOptions
///
public bool Verbose { get; set; } = false;
}
+
+ ///
+ /// Cli options for the Info command
+ ///
+ public class DumpOptions
+ {
+ ///
+ /// File path to the data file
+ ///
+ public FileInfo Datafile { get; set; }
+
+ ///
+ /// Directory path to where to dump all contents
+ ///
+ public DirectoryInfo? Output { get; set; }
+
+ ///
+ /// Determines if Cli should print out verbose logs
+ ///
+ public bool Verbose { get; set; } = false;
+
+ ///
+ /// Names of the code entries that should get dumped
+ ///
+ public string[] Code { get; set; }
+
+ ///
+ /// Determines if strings should get dumped.
+ ///
+ public bool Strings { get; set; }
+
+ ///
+ /// Determines if embedded textures should get dumped
+ ///
+ public bool Textures { get; set; }
+ }
}
\ No newline at end of file
diff --git a/UndertaleModCli/Program.cs b/UndertaleModCli/Program.cs
index 33e66cbd8..523a13232 100644
--- a/UndertaleModCli/Program.cs
+++ b/UndertaleModCli/Program.cs
@@ -12,8 +12,11 @@
using System.CommandLine.Invocation;
using System.CommandLine.Builder;
using System.CommandLine.Parsing;
+using System.Linq;
+using System.Text;
using System.Threading;
using System.Threading.Tasks;
+using UndertaleModLib.Models;
namespace UndertaleModCli
{
@@ -42,9 +45,9 @@ public partial class Program : IScriptInterface
private bool Verbose { get; }
///
- /// File path to where to save the modified data file
+ /// File path or directory path that determines an output for the current Program.
///
- private FileInfo? Output { get; }
+ private FileSystemInfo? Output { get; }
//TODO: document these, these are intertwined with inherited updating methods
private int progressValue;
@@ -75,7 +78,7 @@ public static int Main(string[] args)
{
var verboseOption = new Option(new []{"-v", "--verbose"}, "Detailed logs");
- var dataFileOption = new Argument("datafile", "Path to the data.win/.ios/.droid/.unx file");
+ var dataFileArgument = new Argument("datafile", "Path to the data.win/.ios/.droid/.unx file");
// Setup new command
Command newCommand = new Command("new", "Generates a blank data file")
@@ -88,12 +91,13 @@ public static int Main(string[] args)
newCommand.Handler = CommandHandler.Create(Program.New);
// Setup load command
- var scriptRunnerOption = new Option(new []{ "-s", "--scripts"}, "Scripts to apply to the . ex. a.csx b.csx");
- Command loadCommand = new Command("load", "Load a data file and perform actions on it") {
- dataFileOption,
+ var scriptRunnerOption = new Option(new []{ "-s", "--scripts"}, "Scripts to apply to the . Ex. a.csx b.csx");
+ Command loadCommand = new Command("load", "Load a data file and perform actions on it")
+ {
+ dataFileArgument,
scriptRunnerOption,
verboseOption,
- //TODO: why no force overwrite here, but neded for new?
+ //TODO: why no force overwrite here, but needed for new?
new Option(new []{"-o", "--output"}, "Where to save the modified data file"),
new Option(new []{"-l","--line"}, "Run C# string. Runs AFTER everything else"),
new Option(new []{"-i", "--interactive"}, "Interactive menu launch")
@@ -103,17 +107,31 @@ public static int Main(string[] args)
// Setup info command
Command infoCommand = new Command("info", "Show basic info about the game data file")
{
- dataFileOption,
+ dataFileArgument,
verboseOption
};
infoCommand.Handler = CommandHandler.Create(Program.Info);
+ // Setup dump command
+ Command dumpCommand = new Command("dump", "Dump certain properties about the game data file")
+ {
+ dataFileArgument,
+ verboseOption,
+ new Option(new []{"-o", "--output"}, "Where to dump data file properties to. Will default to path of the data file"),
+ new Option(new[] {"-c", "--code"},
+ "The code files to dump. Ex. gml_Script_init_map gml_Script_reset_map. Specify 'UMT_DUMP_ALL' to dump all code entries"),
+ new Option(new[] {"-s", "--strings"}, "Whether to dump all strings"),
+ new Option(new[] {"-t", "--textures"}, "Whether to dump all embedded textures")
+ };
+ dumpCommand.Handler = CommandHandler.Create(Program.Dump);
+
// Merge everything together
RootCommand rootCommand = new RootCommand
{
newCommand,
loadCommand,
- infoCommand
+ infoCommand,
+ dumpCommand
};
rootCommand.Description = "CLI tool for modding, decompiling and unpacking Undertale (and other Game Maker: Studio games)!";
Parser commandLine = new CommandLineBuilder(rootCommand)
@@ -155,9 +173,15 @@ public Program(FileInfo datafile, FileInfo[]? scripts, FileInfo? output, bool ve
.WithEmitDebugInformation(true);
}
- public Program(FileInfo datafile, bool verbose)
+ public Program(FileInfo datafile, bool verbose, DirectoryInfo output = null)
{
+ Console.WriteLine($"Trying to load file: '{datafile.FullName}'");
+ this.Verbose = verbose;
this.Data = ReadDataFile(datafile, verbose ? WarningHandler : null, verbose ? MessageHandler : null);
+ this.Output = output ?? new DirectoryInfo(datafile.DirectoryName);
+
+ if (this.Verbose)
+ Console.WriteLine("Output directory has been set to " + this.Output.FullName);
}
///
@@ -270,6 +294,61 @@ private static int Info(InfoOptions options)
return EXIT_SUCCESS;
}
+ ///
+ /// Method that gets executed on the "dump" command
+ ///
+ /// The arguments that have been provided with the "dump" command
+ /// and for being successful and failing respectively
+ private static int Dump(DumpOptions options)
+ {
+ //TODO: get rid of a ton of string concat
+
+ Program program;
+ try
+ {
+ program = new Program(options.Datafile, options.Verbose, options.Output);
+ }
+ catch (FileNotFoundException e)
+ {
+ Console.Error.WriteLine(e.Message);
+ return EXIT_FAILURE;
+ }
+
+ // If user provided code to dump, dump code
+ if ((options.Code != null) && (options.Code.Length > 0) && (program.Data.Code.Count > 0))
+ {
+ // If user wanted to dump everything, do that, otherwise only dump what user provided
+ if (options.Code.Contains("UMT_DUMP_ALL"))
+ {
+ foreach (UndertaleCode code in program.Data.Code)
+ {
+ program.DumpCodeEntry(code.Name.Content);
+ }
+ }
+ else
+ {
+ foreach (string code in options.Code)
+ {
+ program.DumpCodeEntry(code);
+ }
+ }
+ }
+
+ // If user wanted to dump strings, dump all of them in a text file
+ if (options.Strings)
+ {
+ program.DumpStrings();
+ }
+
+ // If user wanted to dump embedded textures, dump all of them
+ if (options.Textures)
+ {
+ program.DumpTextures();
+ }
+
+ return EXIT_SUCCESS;
+ }
+
///
/// Runs the interactive menu indefinitely until user quits out of it.
///
@@ -389,6 +468,70 @@ private void CliQuickInfo()
if (IsInteractive) Pause();
}
+ ///
+ /// Dumped a code entry from a data file.
+ ///
+ /// The code entry that should get dumped
+ private void DumpCodeEntry(string codeEntry)
+ {
+ UndertaleCode? code = Data.Code.FirstOrDefault(c => c.Name.Content == codeEntry);
+
+ if (code == null)
+ {
+ Console.Error.WriteLine($"Data file does not contain a code entry named {codeEntry}!");
+ return;
+ }
+
+ string directory = Output.FullName + "/CodeEntries/";
+
+ Directory.CreateDirectory(directory);
+
+ if (Verbose)
+ Console.WriteLine("Dumping " + codeEntry);
+
+ File.WriteAllText(directory + "/" + codeEntry + ".gml", GetDecompiledText(code));
+ }
+
+ ///
+ /// Dumps all strings in a data file.
+ ///
+ private void DumpStrings()
+ {
+ string directory = Output.FullName;
+
+ Directory.CreateDirectory(directory);
+
+ StringBuilder combinedText = new StringBuilder();
+ foreach (UndertaleString dataString in Data.Strings)
+ {
+ if (Verbose)
+ Console.WriteLine("Added " + dataString.Content);
+ combinedText.Append(dataString.Content + "\n");
+ }
+
+ if (Verbose)
+ Console.WriteLine("Writing all strings to disk");
+ File.WriteAllText(directory + "/strings.txt", combinedText.ToString());
+ }
+
+ ///
+ /// Dumps all embedded textures in a data file.
+ ///
+ private void DumpTextures()
+ {
+ string directory = Output.FullName + "/EmbeddedTextures/";
+
+ Directory.CreateDirectory(directory);
+
+ foreach (UndertaleEmbeddedTexture texture in Data.EmbeddedTextures)
+ {
+ if (Verbose)
+ Console.WriteLine("Dumping " + texture.Name);
+ File.WriteAllBytes(directory + "/" + texture.Name.Content + ".png", texture.TextureData.TextureBlob);
+ }
+ }
+
+
///
/// Evaluates and executes the contents of a file as C# Code.
///
From 2628754737b4bbdfa734654be9b6901123062d89 Mon Sep 17 00:00:00 2001
From: Miepee <38186597+Miepee@users.noreply.github.com>
Date: Thu, 21 Apr 2022 18:25:20 +0200
Subject: [PATCH 2/3] CLI: initial replacing support
---
UndertaleModCli/CommandOptions.cs | 36 ++++-
UndertaleModCli/Program.cs | 177 +++++++++++++++++++++++-
UndertaleModLib/Models/UndertaleCode.cs | 1 +
3 files changed, 209 insertions(+), 5 deletions(-)
diff --git a/UndertaleModCli/CommandOptions.cs b/UndertaleModCli/CommandOptions.cs
index 357c8fab5..72f0ff55f 100644
--- a/UndertaleModCli/CommandOptions.cs
+++ b/UndertaleModCli/CommandOptions.cs
@@ -1,7 +1,10 @@
+using System.Collections.Generic;
using System.IO;
namespace UndertaleModCli
{
+ //TODO: split these all up into individual files
+
///
/// Cli options for the New command
///
@@ -81,7 +84,7 @@ public class InfoOptions
}
///
- /// Cli options for the Info command
+ /// Cli options for the Dump command
///
public class DumpOptions
{
@@ -115,4 +118,35 @@ public class DumpOptions
///
public bool Textures { get; set; }
}
+
+ ///
+ /// Cli options for the Replace command
+ ///
+ public class ReplaceOptions
+ {
+ ///
+ /// File path to the data file
+ ///
+ public FileInfo Datafile { get; set; }
+
+ ///
+ /// File path to where to save the modified data file
+ ///
+ public FileInfo? Output { get; set; }
+
+ ///
+ /// Determines if Cli should print out verbose logs
+ ///
+ public bool Verbose { get; set; } = false;
+
+ ///
+ /// Equal separated values of code entry and the file to replace the code entry with.
+ ///
+ public string[] Code { get; set; }
+
+ ///
+ /// Equal separated values of embedded texture and the file to replace the embedded texture with.
+ ///
+ public string[] Textures { get; set; }
+ }
}
\ No newline at end of file
diff --git a/UndertaleModCli/Program.cs b/UndertaleModCli/Program.cs
index 523a13232..d4f345a35 100644
--- a/UndertaleModCli/Program.cs
+++ b/UndertaleModCli/Program.cs
@@ -2,6 +2,7 @@
using Microsoft.CodeAnalysis.Scripting;
using Newtonsoft.Json;
using System;
+using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UndertaleModLib;
@@ -49,6 +50,16 @@ public partial class Program : IScriptInterface
///
private FileSystemInfo? Output { get; }
+ ///
+ /// Constant, used to indicate that the user wants to replace everything in a replace command.
+ ///
+ private const string UMT_REPLACE_ALL = "UMT_REPLACE_ALL";
+
+ ///
+ /// Constant, used to indicate that the user wants to dump everything in a dump command
+ ///
+ private const string UMT_DUMP_ALL = "UMT_DUMP_ALL";
+
//TODO: document these, these are intertwined with inherited updating methods
private int progressValue;
private Task updater;
@@ -119,19 +130,33 @@ public static int Main(string[] args)
verboseOption,
new Option(new []{"-o", "--output"}, "Where to dump data file properties to. Will default to path of the data file"),
new Option(new[] {"-c", "--code"},
- "The code files to dump. Ex. gml_Script_init_map gml_Script_reset_map. Specify 'UMT_DUMP_ALL' to dump all code entries"),
+ $"The code files to dump. Ex. gml_Script_init_map gml_Script_reset_map. Specify '{UMT_DUMP_ALL}' to dump all code entries"),
new Option(new[] {"-s", "--strings"}, "Whether to dump all strings"),
new Option(new[] {"-t", "--textures"}, "Whether to dump all embedded textures")
};
dumpCommand.Handler = CommandHandler.Create(Program.Dump);
+ // Setup replace command
+ Command replaceCommand = new Command("replace", "Replace certain properties in the game data file")
+ {
+ dataFileArgument,
+ verboseOption,
+ new Option(new []{"-o", "--output"}, "Where to save the modified data file"),
+ new Option(new[] {"-c", "--code"},
+ $"Which code files to replace with which file. Ex. 'gml_Script_init_map=./newCode.gml'. It is possible to replace everything by using '{UMT_REPLACE_ALL}'"),
+ new Option(new []{"-t", "--textures"},
+ $"Which embedded texture entry to replace with which file. Ex. 'Texture 0=./newTexture.png'. It is possible to replace everything by using '{UMT_REPLACE_ALL}'")
+ };
+ replaceCommand.Handler = CommandHandler.Create(Program.Replace);
+
// Merge everything together
RootCommand rootCommand = new RootCommand
{
newCommand,
loadCommand,
infoCommand,
- dumpCommand
+ dumpCommand,
+ replaceCommand
};
rootCommand.Description = "CLI tool for modding, decompiling and unpacking Undertale (and other Game Maker: Studio games)!";
Parser commandLine = new CommandLineBuilder(rootCommand)
@@ -318,7 +343,7 @@ private static int Dump(DumpOptions options)
if ((options.Code != null) && (options.Code.Length > 0) && (program.Data.Code.Count > 0))
{
// If user wanted to dump everything, do that, otherwise only dump what user provided
- if (options.Code.Contains("UMT_DUMP_ALL"))
+ if (options.Code.Contains(UMT_DUMP_ALL))
{
foreach (UndertaleCode code in program.Data.Code)
{
@@ -349,6 +374,106 @@ private static int Dump(DumpOptions options)
return EXIT_SUCCESS;
}
+ ///
+ /// Method that gets executed on the "replace" command
+ ///
+ /// The arguments that have been provided with the "replace" command
+ /// and for being successful and failing respectively
+ private static int Replace(ReplaceOptions options)
+ {
+ Program program;
+ try
+ {
+ program = new Program(options.Datafile, null, options.Output, options.Verbose);
+ }
+ catch (FileNotFoundException e)
+ {
+ Console.Error.WriteLine(e.Message);
+ return EXIT_FAILURE;
+ }
+
+ // If user provided code to replace, replace it
+ if ((options.Code != null) && (options.Code.Length > 0) && (program.Data.Code.Count > 0))
+ {
+ // get the values and put them into a dictionary for ease of use
+ Dictionary codeDict = new Dictionary();
+ foreach (string code in options.Code)
+ {
+ string[] splitText = code.Split('=');
+
+ if (splitText.Length != 2)
+ {
+ Console.Error.WriteLine(code + " is malformed! Should be of format 'name_of_code=./newCode.gml' instead!");
+ return EXIT_FAILURE;
+ }
+
+ codeDict.Add(splitText[0], new FileInfo(splitText[1]));
+ }
+
+ // If user wants to replace all, we'll be handling it differently
+ if (codeDict.ContainsKey(UMT_REPLACE_ALL))
+ {
+ string directory = codeDict[UMT_REPLACE_ALL].FullName;
+ foreach (FileInfo file in new DirectoryInfo(directory).GetFiles())
+ {
+ program.ReplaceCodeEntryWithFile(file.Name, file);
+ }
+ }
+ // Otherwise, just replace every file which was given
+ else
+ {
+ foreach (KeyValuePair keyValue in codeDict)
+ {
+ program.ReplaceCodeEntryWithFile(keyValue.Key, keyValue.Value);
+ }
+ }
+
+ }
+
+ // If user provided texture to replace, replace it
+ if ((options.Textures != null) && (options.Textures.Length > 0))
+ {
+ // get the values and put them into a dictionary for ease of use
+ Dictionary textureDict = new Dictionary();
+ foreach (string texture in options.Textures)
+ {
+ string[] splitText = texture.Split('=');
+
+ if (splitText.Length != 2)
+ {
+ Console.Error.WriteLine(texture + " is malformed! Should be of format 'Name=./new.png' instead!");
+ return EXIT_FAILURE;
+ }
+
+ textureDict.Add(splitText[0], new FileInfo(splitText[1]));
+ }
+
+ // If user wants to replace all, we'll be handling it differently
+ if (textureDict.ContainsKey(UMT_REPLACE_ALL))
+ {
+ string directory = textureDict[UMT_REPLACE_ALL].FullName;
+ foreach (FileInfo file in new DirectoryInfo(directory).GetFiles())
+ {
+ program.ReplaceTextureWithFile(file.Name, file);
+ }
+ }
+ // Otherwise, just replace every file which was given
+ else
+ {
+ foreach (KeyValuePair keyValue in textureDict)
+ {
+ program.ReplaceTextureWithFile(keyValue.Key, keyValue.Value);
+ }
+ }
+ }
+
+ // if parameter to save file was given, save the data file
+ if (options.Output != null)
+ program.SaveDataFile(options.Output.FullName);
+
+ return EXIT_SUCCESS;
+ }
+
///
/// Runs the interactive menu indefinitely until user quits out of it.
///
@@ -531,6 +656,47 @@ private void DumpTextures()
}
}
+ ///
+ /// Replaces a code entry with text from another file.
+ ///
+ /// The code entry to replace
+ /// File path which should replace the code entry.
+ private void ReplaceCodeEntryWithFile(string codeEntry, FileInfo fileToReplace)
+ {
+ UndertaleCode? code = Data.Code.FirstOrDefault(c => c.Name.Content == codeEntry);
+
+ if (code == null)
+ {
+ Console.Error.WriteLine($"Data file does not contain a code entry named {codeEntry}!");
+ return;
+ }
+
+ if (Verbose)
+ Console.WriteLine("Replacing " + codeEntry);
+
+ ImportGMLString(codeEntry, File.ReadAllText(fileToReplace.FullName));
+ }
+
+ ///
+ /// Replaces an embedded texture with contents from another file.
+ ///
+ /// Embedded texture to replace
+ /// File path which should replace the embedded texture.
+ private void ReplaceTextureWithFile(string textureEntry, FileInfo fileToReplace)
+ {
+ UndertaleEmbeddedTexture? texture = Data.EmbeddedTextures.FirstOrDefault(t => t.Name.Content == textureEntry);
+
+ if (texture == null)
+ {
+ Console.Error.WriteLine($"Data file does not contain an embedded texture named {textureEntry}!");
+ return;
+ }
+
+ if (Verbose)
+ Console.WriteLine("Replacing " + textureEntry);
+
+ texture.TextureData.TextureBlob = File.ReadAllBytes(fileToReplace.FullName);
+ }
///
/// Evaluates and executes the contents of a file as C# Code.
@@ -619,7 +785,10 @@ private static UndertaleData ReadDataFile(FileInfo datafile, WarningHandlerDeleg
try
{
using FileStream fs = datafile.OpenRead();
- return UndertaleIO.Read(fs, warningHandler, messageHandler);
+ UndertaleData gmData = UndertaleIO.Read(fs, warningHandler, messageHandler);
+ //TODO: this should be handled in UTCode, not here
+ gmData.ToolInfo.AppDataProfiles = "";
+ return gmData;
}
catch (FileNotFoundException e)
{
diff --git a/UndertaleModLib/Models/UndertaleCode.cs b/UndertaleModLib/Models/UndertaleCode.cs
index 02ea9b921..261561148 100644
--- a/UndertaleModLib/Models/UndertaleCode.cs
+++ b/UndertaleModLib/Models/UndertaleCode.cs
@@ -1257,6 +1257,7 @@ public void ReplaceGML(string gmlCode, UndertaleData data)
data.GMLCacheChanged?.Add(Name.Content);
+ //TODO: only do this if profile mode is enabled in the first place
try
{
// When necessary, write to profile.
From ec75760adfcf8cd53e3b31c098a897463e1e5043 Mon Sep 17 00:00:00 2001
From: Miepee <38186597+Miepee@users.noreply.github.com>
Date: Tue, 26 Apr 2022 12:46:47 +0200
Subject: [PATCH 3/3] Cli: some cleanup of dump+replace
---
UndertaleModCli/Program.cs | 78 ++++++++++++++------------------------
1 file changed, 29 insertions(+), 49 deletions(-)
diff --git a/UndertaleModCli/Program.cs b/UndertaleModCli/Program.cs
index d4f345a35..df85c2716 100644
--- a/UndertaleModCli/Program.cs
+++ b/UndertaleModCli/Program.cs
@@ -326,8 +326,6 @@ private static int Info(InfoOptions options)
/// and for being successful and failing respectively
private static int Dump(DumpOptions options)
{
- //TODO: get rid of a ton of string concat
-
Program program;
try
{
@@ -343,33 +341,23 @@ private static int Dump(DumpOptions options)
if ((options.Code != null) && (options.Code.Length > 0) && (program.Data.Code.Count > 0))
{
// If user wanted to dump everything, do that, otherwise only dump what user provided
+ string[] codeArray;
if (options.Code.Contains(UMT_DUMP_ALL))
- {
- foreach (UndertaleCode code in program.Data.Code)
- {
- program.DumpCodeEntry(code.Name.Content);
- }
- }
+ codeArray = program.Data.Code.Select(c => c.Name.Content).ToArray();
else
- {
- foreach (string code in options.Code)
- {
- program.DumpCodeEntry(code);
- }
- }
+ codeArray = options.Code;
+
+ foreach (string code in codeArray)
+ program.DumpCodeEntry(code);
}
// If user wanted to dump strings, dump all of them in a text file
if (options.Strings)
- {
- program.DumpStrings();
- }
+ program.DumpAllStrings();
// If user wanted to dump embedded textures, dump all of them
if (options.Textures)
- {
- program.DumpTextures();
- }
+ program.DumpAllTextures();
return EXIT_SUCCESS;
}
@@ -392,7 +380,7 @@ private static int Replace(ReplaceOptions options)
return EXIT_FAILURE;
}
- // If user provided code to replace, replace it
+ // If user provided code to replace, replace them
if ((options.Code != null) && (options.Code.Length > 0) && (program.Data.Code.Count > 0))
{
// get the values and put them into a dictionary for ease of use
@@ -403,34 +391,29 @@ private static int Replace(ReplaceOptions options)
if (splitText.Length != 2)
{
- Console.Error.WriteLine(code + " is malformed! Should be of format 'name_of_code=./newCode.gml' instead!");
+ Console.Error.WriteLine($"{code} is malformed! Should be of format 'name_of_code=./newCode.gml' instead!");
return EXIT_FAILURE;
}
codeDict.Add(splitText[0], new FileInfo(splitText[1]));
}
- // If user wants to replace all, we'll be handling it differently
+ // If user wants to replace all, we'll be handling it differently. Replace every file from the provided directory
if (codeDict.ContainsKey(UMT_REPLACE_ALL))
{
string directory = codeDict[UMT_REPLACE_ALL].FullName;
foreach (FileInfo file in new DirectoryInfo(directory).GetFiles())
- {
program.ReplaceCodeEntryWithFile(file.Name, file);
- }
}
// Otherwise, just replace every file which was given
else
{
foreach (KeyValuePair keyValue in codeDict)
- {
program.ReplaceCodeEntryWithFile(keyValue.Key, keyValue.Value);
- }
}
-
}
- // If user provided texture to replace, replace it
+ // If user provided texture to replace, replace them
if ((options.Textures != null) && (options.Textures.Length > 0))
{
// get the values and put them into a dictionary for ease of use
@@ -441,29 +424,25 @@ private static int Replace(ReplaceOptions options)
if (splitText.Length != 2)
{
- Console.Error.WriteLine(texture + " is malformed! Should be of format 'Name=./new.png' instead!");
+ Console.Error.WriteLine($"{texture} is malformed! Should be of format 'Name=./new.png' instead!");
return EXIT_FAILURE;
}
textureDict.Add(splitText[0], new FileInfo(splitText[1]));
}
- // If user wants to replace all, we'll be handling it differently
+ // If user wants to replace all, we'll be handling it differently. Replace every file from the provided directory
if (textureDict.ContainsKey(UMT_REPLACE_ALL))
{
string directory = textureDict[UMT_REPLACE_ALL].FullName;
foreach (FileInfo file in new DirectoryInfo(directory).GetFiles())
- {
program.ReplaceTextureWithFile(file.Name, file);
- }
}
// Otherwise, just replace every file which was given
else
{
- foreach (KeyValuePair keyValue in textureDict)
- {
- program.ReplaceTextureWithFile(keyValue.Key, keyValue.Value);
- }
+ foreach ((string key, FileInfo value) in textureDict)
+ program.ReplaceTextureWithFile(key, value);
}
}
@@ -487,6 +466,7 @@ private void RunInteractiveMenu()
Console.WriteLine("3 - Save and overwrite.");
Console.WriteLine("4 - Save to different place.");
Console.WriteLine("5 - Display quick info.");
+ //TODO: add dumping and replacing options
Console.WriteLine("6 - Quit without saving.");
Console.Write("Input, please: ");
@@ -594,7 +574,7 @@ private void CliQuickInfo()
}
///
- /// Dumped a code entry from a data file.
+ /// Dumps a code entry from a data file.
///
/// The code entry that should get dumped
private void DumpCodeEntry(string codeEntry)
@@ -607,20 +587,20 @@ private void DumpCodeEntry(string codeEntry)
return;
}
- string directory = Output.FullName + "/CodeEntries/";
+ string directory = $"{Output.FullName}/CodeEntries/";
Directory.CreateDirectory(directory);
if (Verbose)
- Console.WriteLine("Dumping " + codeEntry);
+ Console.WriteLine($"Dumping {codeEntry}");
- File.WriteAllText(directory + "/" + codeEntry + ".gml", GetDecompiledText(code));
+ File.WriteAllText($"{directory}/{codeEntry}.gml", GetDecompiledText(code));
}
///
/// Dumps all strings in a data file.
///
- private void DumpStrings()
+ private void DumpAllStrings()
{
string directory = Output.FullName;
@@ -630,29 +610,29 @@ private void DumpStrings()
foreach (UndertaleString dataString in Data.Strings)
{
if (Verbose)
- Console.WriteLine("Added " + dataString.Content);
- combinedText.Append(dataString.Content + "\n");
+ Console.WriteLine($"Added {dataString.Content}");
+ combinedText.Append($"{dataString.Content}\n");
}
if (Verbose)
Console.WriteLine("Writing all strings to disk");
- File.WriteAllText(directory + "/strings.txt", combinedText.ToString());
+ File.WriteAllText($"{directory}/strings.txt", combinedText.ToString());
}
///
/// Dumps all embedded textures in a data file.
///
- private void DumpTextures()
+ private void DumpAllTextures()
{
- string directory = Output.FullName + "/EmbeddedTextures/";
+ string directory = $"{Output.FullName}/EmbeddedTextures/";
Directory.CreateDirectory(directory);
foreach (UndertaleEmbeddedTexture texture in Data.EmbeddedTextures)
{
if (Verbose)
- Console.WriteLine("Dumping " + texture.Name);
- File.WriteAllBytes(directory + "/" + texture.Name.Content + ".png", texture.TextureData.TextureBlob);
+ Console.WriteLine($"Dumping {texture.Name}");
+ File.WriteAllBytes($"{directory}/{texture.Name.Content}.png", texture.TextureData.TextureBlob);
}
}