diff --git a/AM2RPortHelperLib/AM2RPortHelperLib.csproj b/AM2RPortHelperLib/AM2RPortHelperLib.csproj
index caba697..d242e7e 100644
--- a/AM2RPortHelperLib/AM2RPortHelperLib.csproj
+++ b/AM2RPortHelperLib/AM2RPortHelperLib.csproj
@@ -28,4 +28,19 @@
+
+
+ ResXFileCodeGenerator
+ Resources.Designer.cs
+
+
+
+
+
+ True
+ True
+ Resources#.resx
+
+
+
diff --git a/AM2RPortHelperLib/HelperMethods.cs b/AM2RPortHelperLib/HelperMethods.cs
index 1d8cfaf..3ea96f7 100644
--- a/AM2RPortHelperLib/HelperMethods.cs
+++ b/AM2RPortHelperLib/HelperMethods.cs
@@ -73,7 +73,7 @@ public static class HelperMethods
/// The filepath where the resized image should be saved to.
///
///
- /// Image iconPath = Image.Load("iconPath.png");
+ /// string iconPath = "iconPath.png";
/// SaveAndroidIcon(iconPath, 128, "128.png");
///
///
@@ -84,7 +84,7 @@ public static class HelperMethods
picture.Mutate(x => x.Resize(dimensions, dimensions, KnownResamplers.NearestNeighbor));
picture.SaveAsPng(filePath);
}
-
+
///
/// Calculates the SHA256 hash of a specified file.
///
diff --git a/AM2RPortHelperLib/IMods.cs b/AM2RPortHelperLib/IMods.cs
index 078d917..5d1955b 100644
--- a/AM2RPortHelperLib/IMods.cs
+++ b/AM2RPortHelperLib/IMods.cs
@@ -14,7 +14,7 @@ public abstract class IMods
///
/// A temporary directory
///
- protected static readonly string tmp = Path.GetTempPath();
+ protected static readonly string tmp = Path.GetTempPath() + "/PortHelper/";
///
/// The current directory of the AM2RPortHelper program.
diff --git a/AM2RPortHelperLib/RawMods.cs b/AM2RPortHelperLib/RawMods.cs
index 1963279..eba67d8 100644
--- a/AM2RPortHelperLib/RawMods.cs
+++ b/AM2RPortHelperLib/RawMods.cs
@@ -1,7 +1,9 @@
using System.Diagnostics;
using System.IO.Compression;
using System.Runtime.InteropServices;
+using System.Security;
using System.Text.RegularExpressions;
+using SixLabors.ImageSharp;
using UndertaleModLib;
using static AM2RPortHelperLib.Core;
@@ -29,7 +31,41 @@ public abstract class RawMods : IMods
throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
}
-
+
+ private static string GetProperPathToBuiltinIcons(string nameOfResource)
+ {
+ string subCaseFunction(string resource)
+ {
+ // TODO: default path should be in XDG_CONFIG
+ string origPath = utilDir + "/" + resource;
+ if (File.Exists(origPath))
+ return origPath;
+
+ var byteArray = resource switch
+ {
+ nameof(Resources.icon) + ".png" => Resources.icon,
+ nameof(Resources.splash) + ".png" => Resources.splash,
+ nameof(Resources.splashAndroid) + ".png" => Resources.splashAndroid,
+ _ => throw new InvalidDataException("SubCaseFunction was called with an improper resource!")
+ };
+
+ Image.Load(byteArray).SaveAsPng(tmp + "/" + resource);
+ origPath = tmp + "/" + resource;
+ return origPath;
+ }
+
+ switch (nameOfResource)
+ {
+ case nameof(Resources.icon):
+ return subCaseFunction(nameof(Resources.icon) + ".png");
+ case nameof(Resources.splash):
+ return subCaseFunction(nameof(Resources.splash) + ".png");
+ case nameof(Resources.splashAndroid):
+ return subCaseFunction(nameof(Resources.splashAndroid) + ".png");
+ default: throw new InvalidDataException(nameOfResource + " is an unknown Icon!");
+ }
+ }
+
// TODO: Port to Windows
public static void PortToWindows(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputHandlerDelegate = null)
{
@@ -82,9 +118,9 @@ public abstract class RawMods : IMods
File.Copy(utilDir + "/runner", extractDirectory + "/runner");
if (!File.Exists(assetsDir + "/icon.png"))
- File.Copy(utilDir + "/icon.png", assetsDir + "/icon.png");
+ File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.icon)), assetsDir + "/icon.png");
if (!File.Exists(assetsDir + "/splash.png"))
- File.Copy(utilDir + "/splash.png", assetsDir + "/splash.png");
+ File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.splash)), assetsDir + "/splash.png");
//recursively lowercase everything in the assets folder
HelperMethods.LowercaseFolder(assetsDir);
@@ -94,7 +130,7 @@ public abstract class RawMods : IMods
ZipFile.CreateFromDirectory(extractDirectory, outputRawZipPath);
// Clean up
- Directory.Delete(assetsDir, true);
+ Directory.Delete(tmp, true);
}
public static void PortToAndroid(string inputRawZipPath, string outputRawApkPath, bool useCustomSaveDirectory = false, bool usesInternet = false, OutputHandlerDelegate outputDelegate = null)
@@ -104,7 +140,6 @@ public abstract class RawMods : IMods
outputHandler = outputDelegate;
string extractDirectory = tmp + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
- string unzipDir = extractDirectory + "/zip";
string apkDir = extractDirectory + "/apk";
string apkAssetsDir = apkDir + "/assets";
string bin = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "cmd.exe" : "java";
@@ -160,8 +195,8 @@ public abstract class RawMods : IMods
default: throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
}
- if (!File.Exists(apkAssetsDir + "/splash.png"))
- File.Copy(utilDir + "/splashAndroid.png", apkAssetsDir + "/splash.png", true);
+ // The wrapper always has a splash image, so we want to overwrite it.
+ File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.splashAndroid)), apkAssetsDir + "/splash.png", true);
//recursively lowercase everything in the assets folder
HelperMethods.LowercaseFolder(apkAssetsDir);
@@ -171,10 +206,10 @@ public abstract class RawMods : IMods
yamlFile = yamlFile.Replace("doNotCompress:", "doNotCompress:\n- ogg");
File.WriteAllText(apkDir + "/apktool.yml", yamlFile);
- // Edit the icons in the apk
+ // Edit the icons in the apk. Wrapper always has these, so we need to overwrite these too.
string resPath = apkDir + "/res";
- // TODO: icon should only be read from if its there, otherwise default frog icon should be in the assembly
- string origPath = utilDir + "/icon.png";
+ // Icon should only be read from if its there, otherwise default frog icon should be in the assembly
+ string origPath = GetProperPathToBuiltinIcons(nameof(Resources.icon));
HelperMethods.SaveAndroidIcon(origPath, 96, resPath + "/drawable/icon.png");
HelperMethods.SaveAndroidIcon(origPath, 72, resPath + "/drawable-hdpi-v4/icon.png");
HelperMethods.SaveAndroidIcon(origPath, 36, resPath + "/drawable-ldpi-v4/icon.png");
@@ -273,7 +308,7 @@ public abstract class RawMods : IMods
File.Move(finalApkBuild, outputRawApkPath);
// Clean up
- Directory.Delete(extractDirectory, true);
+ Directory.Delete(tmp, true);
}
public static void PortToMac(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputDelegate = null)
@@ -324,10 +359,11 @@ public abstract class RawMods : IMods
default: throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
}
+ // TODO: do we really want to keep their images?
if (!File.Exists(assetsDir + "/icon.png"))
- File.Copy(utilDir + "/icon.png", extractDirectory + "/icon.png");
+ File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.icon)), extractDirectory + "/icon.png");
if (!File.Exists(assetsDir + "/splash.png"))
- File.Copy(utilDir + "/splash.png", extractDirectory + "/splash.png");
+ File.Copy(GetProperPathToBuiltinIcons(nameof(Resources.splash)), extractDirectory + "/splash.png");
// Delete fonts folder if it exists, because I need to convert bytecode version from game and newer version doesn't support font loading
if (Directory.Exists(extractDirectory + "/lang/fonts"))
@@ -379,8 +415,8 @@ public abstract class RawMods : IMods
UndertaleData gmData = UndertaleIO.Read(fs, SendOutput, SendOutput);
modName = gmData.GeneralInfo.DisplayName.Content;
}
- //TODO: handle error on special characters, but need to know which characters are invalid in the first place
- //if (modName.Contains())
+ // Escape invalid xml characters
+ modName = SecurityElement.Escape(modName);
SendOutput("Editing Runner references to AM2R...");
string textFile = File.ReadAllText(assetsDir + "/yoyorunner.config");
textFile = textFile.Replace("YoYo Runner", modName);
@@ -401,6 +437,6 @@ public abstract class RawMods : IMods
ZipFile.CreateFromDirectory(baseTempDirectory, outputRawZipPath);
// Clean up
- Directory.Delete(baseTempDirectory, true);
+ Directory.Delete(tmp, true);
}
}
\ No newline at end of file
diff --git a/AM2RPortHelperLib/Resources.Designer.cs b/AM2RPortHelperLib/Resources.Designer.cs
new file mode 100644
index 0000000..333e613
--- /dev/null
+++ b/AM2RPortHelperLib/Resources.Designer.cs
@@ -0,0 +1,78 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace AM2RPortHelperLib {
+ using System;
+
+
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
+ [System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Resources {
+
+ private static System.Resources.ResourceManager resourceMan;
+
+ private static System.Globalization.CultureInfo resourceCulture;
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Resources() {
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.Equals(null, resourceMan)) {
+ System.Resources.ResourceManager temp = new System.Resources.ResourceManager("AM2RPortHelperLib.Resources", typeof(Resources).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] icon {
+ get {
+ object obj = ResourceManager.GetObject("icon", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] splash {
+ get {
+ object obj = ResourceManager.GetObject("splash", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+
+ ///
+ /// Looks up a localized resource of type System.Byte[].
+ ///
+ internal static byte[] splashAndroid {
+ get {
+ object obj = ResourceManager.GetObject("splashAndroid", resourceCulture);
+ return ((byte[])(obj));
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/AM2RPortHelperLib/Resources.resx b/AM2RPortHelperLib/Resources.resx
new file mode 100644
index 0000000..572ed8f
--- /dev/null
+++ b/AM2RPortHelperLib/Resources.resx
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 1.3
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Resources\icon.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Resources\splash.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ Resources\splashAndroid.png;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/AM2RPortHelperLib/utils/icon.png b/AM2RPortHelperLib/Resources/icon.png
similarity index 100%
rename from AM2RPortHelperLib/utils/icon.png
rename to AM2RPortHelperLib/Resources/icon.png
diff --git a/AM2RPortHelperLib/utils/splash.png b/AM2RPortHelperLib/Resources/splash.png
similarity index 100%
rename from AM2RPortHelperLib/utils/splash.png
rename to AM2RPortHelperLib/Resources/splash.png
diff --git a/AM2RPortHelperLib/utils/splashAndroid.png b/AM2RPortHelperLib/Resources/splashAndroid.png
similarity index 100%
rename from AM2RPortHelperLib/utils/splashAndroid.png
rename to AM2RPortHelperLib/Resources/splashAndroid.png