diff --git a/AM2RPortHelperLib/Core.cs b/AM2RPortHelperLib/Core.cs
index 84e01df..27fdb4d 100644
--- a/AM2RPortHelperLib/Core.cs
+++ b/AM2RPortHelperLib/Core.cs
@@ -7,7 +7,7 @@ public class Core
///
public const string Version = "1.4";
- public enum LauncherModTargets
+ public enum ModOS
{
Windows,
Linux,
diff --git a/AM2RPortHelperLib/HelperMethods.cs b/AM2RPortHelperLib/HelperMethods.cs
index e0b0ff8..71426b3 100644
--- a/AM2RPortHelperLib/HelperMethods.cs
+++ b/AM2RPortHelperLib/HelperMethods.cs
@@ -17,19 +17,23 @@ public static class HelperMethods
foreach(var file in dir.GetFiles())
{
if (file.Name == file.Name.ToLower()) continue;
- file.MoveTo(file.DirectoryName + "/" + file.Name.ToLower());
+ // Windows is dumb, thus we need to move in two trips
+ file.MoveTo(file.DirectoryName + "/" + file.Name.ToLower() + "_");
+ file.MoveTo(file.FullName.Substring(0, file.FullName.Length-1));
}
foreach(var subDir in dir.GetDirectories())
{
if (subDir.Name == subDir.Name.ToLower()) continue;
// ReSharper disable once PossibleNullReferenceException - since this is a subdirectory, it always has a parent
- subDir.MoveTo(subDir.Parent.FullName + "/" + subDir.Name.ToLower());
+ // Windows is dumb, thus we need to move in two trips
+ subDir.MoveTo(subDir.Parent.FullName + "/" + subDir.Name.ToLower() + "_");
+ subDir.MoveTo(subDir.FullName.Substring(0, subDir.FullName.Length-1));
LowercaseFolder(subDir.FullName);
}
}
- public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs)
+ public static void DirectoryCopy(string sourceDirName, string destDirName, bool copySubDirs = true)
{
// Get the subdirectories for the specified directory.
DirectoryInfo dir = new DirectoryInfo(sourceDirName);
diff --git a/AM2RPortHelperLib/LauncherMods.cs b/AM2RPortHelperLib/LauncherMods.cs
index 48d23d2..4ae6d79 100644
--- a/AM2RPortHelperLib/LauncherMods.cs
+++ b/AM2RPortHelperLib/LauncherMods.cs
@@ -8,14 +8,14 @@ public abstract class LauncherMods : IMods
/// Ports a Mod zip intended to be installed via the AM2RLauncher to other operating systems.
///
/// The path to the AM2RLauncher mod zip that should be ported.
- /// The target operating system to port the
+ /// The target operating system to port the
/// Whether Android should be inlcuded in the port.
/// The path where the ported AM2RLauncher mod zip should be saved.
/// The path to an AM2R 1.1 zip path. This is *required* if the input launcher zip is for Mac and will be ignored if the input zip is for anything else.
/// The function that should handle in-progress output messages.
/// WIP
/// TODO: other exceptions
- public static void PortLauncherMod(string inputLauncherZipPath, Core.LauncherModTargets targetOS, bool includeAndroid, string outputLauncherZipPath, string am2r11ZipPath = null, OutputHandlerDelegate outputDelegate = null)
+ public static void PortLauncherMod(string inputLauncherZipPath, Core.ModOS modTarget, bool includeAndroid, string outputLauncherZipPath, string am2r11ZipPath = null, OutputHandlerDelegate outputDelegate = null)
{
outputHandler = outputDelegate;
string extractDirectory = tmp + "/" + Path.GetFileNameWithoutExtension(inputLauncherZipPath);
@@ -34,7 +34,7 @@ public abstract class LauncherMods : IMods
string currentOS = profile.OperatingSystem;
bool isAndroidIncluded = profile.SupportsAndroid;
- if (targetOS.ToString() == profile.OperatingSystem)
+ if (modTarget.ToString() == profile.OperatingSystem)
{
SendOutput("Target OS and Launcher OS are the same; exiting.");
return;
@@ -53,9 +53,9 @@ public abstract class LauncherMods : IMods
if (profile.OperatingSystem == "Mac")
throw new NotSupportedException("Porting Mac mods is currently not supported!");
- switch (targetOS)
+ switch (modTarget)
{
- case Core.LauncherModTargets.Windows:
+ case Core.ModOS.Windows:
{
// We have a non-windows launcher mod, where data file patch is guaranteed to be game.xdelta
File.Move(extractDirectory + "/game.xdelta", extractDirectory + "/data.xdelta");
@@ -84,7 +84,7 @@ public abstract class LauncherMods : IMods
break;
}
- case Core.LauncherModTargets.Linux:
+ case Core.ModOS.Linux:
{
if (currentOS == "Windows")
File.Move(extractDirectory + "/data.xdelta", extractDirectory + "/game.xdelta");
@@ -115,13 +115,13 @@ public abstract class LauncherMods : IMods
break;
}
- case Core.LauncherModTargets.Mac:
+ case Core.ModOS.Mac:
{
// TODO: Not sure if this is ever gonna be possible, since it requires one to shift up the patch.
// We'd need a 1.1 file to apply the patch to, run that with umtlib to shift it up, and then apply a new patch.
throw new NotSupportedException("Porting Mac mods is currently not supported!");
}
- default: throw new ArgumentOutOfRangeException(nameof(targetOS), targetOS, "Unknown target to port to!");
+ default: throw new ArgumentOutOfRangeException(nameof(modTarget), modTarget, "Unknown target to port to!");
}
if (!includeAndroid)
@@ -143,7 +143,7 @@ public abstract class LauncherMods : IMods
}
//zip the result
- SendOutput($"Creating Launcher zip for {targetOS}...");
+ SendOutput($"Creating Launcher zip for {modTarget}...");
ZipFile.CreateFromDirectory(extractDirectory, outputLauncherZipPath);
// Clean up
diff --git a/AM2RPortHelperLib/RawMods.cs b/AM2RPortHelperLib/RawMods.cs
index 5cc7a6d..7d6eed7 100644
--- a/AM2RPortHelperLib/RawMods.cs
+++ b/AM2RPortHelperLib/RawMods.cs
@@ -1,15 +1,49 @@
using System.Diagnostics;
using System.IO.Compression;
using System.Runtime.InteropServices;
+using static AM2RPortHelperLib.Core;
namespace AM2RPortHelperLib;
public abstract class RawMods : IMods
{
- // TODO: Make these not windows -> OS, but Raw -> OS
- public static void PortToLinux(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputDelegate = null)
+ // For completionist sake, it should be possible to also port raw APKs to win/lin/mac
+ // But until some person actually shows up that needs this feature, I'm too lazy to implement it
+
+
+ private static ModOS GetModOSOfRawZip(string inputRawZipPath)
{
+ ZipArchive archive = ZipFile.OpenRead(inputRawZipPath);
+ if (archive.Entries.Any(f => f.FullName == "AM2R.exe") && archive.Entries.Any(f => f.FullName == "data.win"))
+ return ModOS.Linux;
+ if (archive.Entries.Any(f => f.FullName == "runner") && archive.Entries.Any(f => f.FullName == "assets/game.unx"))
+ return ModOS.Linux;
+
+ // I probably *should* use fullpaths for these, but the .app file could technically be different and don't want to thinka bout how to circumvent it
+ if (archive.Entries.Any(f => f.FullName.Contains("Contents/MacOS/Mac_Runner")) && archive.Entries.Any(f => f.FullName.Contains("Contents/Resources/game.ios")))
+ return ModOS.Mac;
+
+ throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
+ }
+
+ // TODO: Port to Windows
+ public static void PortToWindows(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputHandlerDelegate = null)
+ {
+ throw new NotImplementedException();
+ }
+
+ public static void PortToLinux(string inputRawZipPath, string outputRawZipPath, OutputHandlerDelegate outputDelegate = null)
+ {
+ ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
+ SendOutput("Zip Recognized as " + currentOS);
+
+ if (currentOS == ModOS.Linux)
+ {
+ SendOutput("Zip is already a raw Linux zip.");
+ return;
+ }
+
outputHandler = outputDelegate;
string extractDirectory = tmp + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string assetsDir = extractDirectory + "/assets";
@@ -17,26 +51,31 @@ public abstract class RawMods : IMods
// Check if temp folder exists, delete if yes, extract zip to there
if (Directory.Exists(extractDirectory))
Directory.Delete(extractDirectory, true);
- SendOutput("Extracting Linux...");
- ZipFile.ExtractToDirectory(inputRawZipPath, extractDirectory);
-
- // Move everything into assets folder
- SendOutput("Moving into Linux assets folder...");
+ SendOutput("Extracting for Raw Linux...");
Directory.CreateDirectory(assetsDir);
- foreach (var file in new DirectoryInfo(extractDirectory).GetFiles())
- file.MoveTo(assetsDir + "/" + file.Name);
-
- foreach (var dir in new DirectoryInfo(extractDirectory).GetDirectories())
- {
- if (dir.Name == "assets") continue;
- dir.MoveTo(assetsDir + "/" + dir.Name);
- }
-
+ ZipFile.ExtractToDirectory(inputRawZipPath, assetsDir);
+
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Linux and lowercase them...");
- File.Delete(assetsDir + "/AM2R.exe");
- File.Delete(assetsDir + "/D3DX9_43.dll");
- File.Move(assetsDir + "/data.win", assetsDir + "/game.unx");
+ switch (currentOS)
+ {
+ case ModOS.Windows:
+ File.Delete(assetsDir + "/AM2R.exe");
+ File.Delete(assetsDir + "/D3DX9_43.dll");
+ File.Move(assetsDir + "/data.win", assetsDir + "/game.unx");
+ break;
+ case ModOS.Mac:
+ var appDir = new DirectoryInfo(assetsDir).GetDirectories().First(n => n.Name.EndsWith(".app"));
+ HelperMethods.DirectoryCopy(assetsDir + "/" + appDir.Name + "/Contents/Resources", assetsDir);
+ File.Delete(assetsDir + "/gamecontrollerdb.txt");
+ File.Delete(assetsDir + "/yoyorunner.config");
+ Directory.Delete(assetsDir + "/English.lproj", true);
+ Directory.Delete(assetsDir + "/" + appDir.Name, true);
+ File.Move(assetsDir + "/game.ios", assetsDir + "/game.unx");
+ break;
+ default: throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
+ }
+
File.Copy(utilDir + "/runner", extractDirectory + "/runner");
if (!File.Exists(assetsDir + "/icon.png"))
File.Copy(utilDir + "/icon.png", assetsDir + "/icon.png");
@@ -47,16 +86,19 @@ public abstract class RawMods : IMods
HelperMethods.LowercaseFolder(assetsDir);
//zip the result
- SendOutput("Creating Linux zip...");
+ SendOutput("Creating raw Linux zip...");
ZipFile.CreateFromDirectory(extractDirectory, outputRawZipPath);
// Clean up
Directory.Delete(assetsDir, true);
}
-
+
// TODO: try to figure out if its possible to extract the name from the data.win file and then just offer a "use custom save directory" option that decides whether to use it or not.
public static void PortToAndroid(string inputRawZipPath, string outputRawApkPath, string modName = null, bool usesInternet = false, OutputHandlerDelegate outputDelegate = null)
{
+ ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
+ SendOutput("Zip Recognized as " + currentOS);
+
outputHandler = outputDelegate;
string extractDirectory = tmp + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string unzipDir = extractDirectory + "/zip";
@@ -72,8 +114,6 @@ public abstract class RawMods : IMods
if (Directory.Exists(extractDirectory))
Directory.Delete(extractDirectory, true);
Directory.CreateDirectory(extractDirectory);
- SendOutput("Extracting...");
- ZipFile.ExtractToDirectory(inputRawZipPath, unzipDir);
// Run APKTOOL and decompress the file
SendOutput("Decompiling apk...");
@@ -87,20 +127,38 @@ public abstract class RawMods : IMods
p.Start();
p.WaitForExit();
- // Move everything into assets folder
- SendOutput("Move into Android assets folder...");
- foreach (var file in new DirectoryInfo(unzipDir).GetFiles())
- file.MoveTo(apkAssetsDir + "/" + file.Name);
-
- foreach (var dir in new DirectoryInfo(unzipDir).GetDirectories())
- dir.MoveTo(apkAssetsDir + "/" + dir.Name);
-
+ SendOutput("Extracting for Raw Android...");
+ ZipFile.ExtractToDirectory(inputRawZipPath, apkAssetsDir);
+
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Android and lowercase them...");
- File.Delete(apkAssetsDir + "/AM2R.exe");
- File.Delete(apkAssetsDir + "/D3DX9_43.dll");
- File.Move(apkAssetsDir + "/data.win", apkAssetsDir + "/game.droid");
- File.Copy(utilDir + "/splashAndroid.png", apkAssetsDir + "/splash.png", true);
+ switch (currentOS)
+ {
+ case ModOS.Windows:
+ File.Delete(apkAssetsDir + "/AM2R.exe");
+ File.Delete(apkAssetsDir + "/D3DX9_43.dll");
+ File.Move(apkAssetsDir + "/data.win", apkAssetsDir + "/game.droid");
+ break;
+ case ModOS.Linux:
+ File.Delete(apkAssetsDir + "/runner");
+ HelperMethods.DirectoryCopy(apkAssetsDir + "/assets", apkAssetsDir);
+ Directory.Delete(apkAssetsDir + "/assets", true);
+ File.Move(apkAssetsDir + "/game.unx", apkAssetsDir + "/game.droid");
+ break;
+ case ModOS.Mac:
+ var appDir = new DirectoryInfo(apkAssetsDir).GetDirectories().First(n => n.Name.EndsWith(".app"));
+ HelperMethods.DirectoryCopy(apkAssetsDir + "/" + appDir.Name + "/Contents/Resources", apkAssetsDir);
+ File.Delete(apkAssetsDir + "/gamecontrollerdb.txt");
+ File.Delete(apkAssetsDir + "/yoyorunner.config");
+ Directory.Delete(apkAssetsDir + "/English.lproj", true);
+ Directory.Delete(apkAssetsDir + "/" + appDir.Name, true);
+ File.Move(apkAssetsDir + "/game.ios", apkAssetsDir + "/game.droid");
+ break;
+ 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);
//recursively lowercase everything in the assets folder
HelperMethods.LowercaseFolder(apkAssetsDir);
@@ -121,7 +179,7 @@ public abstract class RawMods : IMods
HelperMethods.SaveAndroidIcon(origPath, 144, resPath + "/drawable-xxhdpi-v4/icon.png");
HelperMethods.SaveAndroidIcon(origPath, 192, resPath + "/drawable-xxxhdpi-v4/icon.png");
- // Hermite probably the best
+ // TODO: Hermite probably best as image upscaler, but we'll see
// On certain occasions, we need to modify the manifest file.
if (modName != null || usesInternet)
@@ -205,6 +263,15 @@ public abstract class RawMods : IMods
//TODO: try to figure out if its possible to extract the name from the data.win file? They do have a displayname option last time I checked...
public static void PortToMac(string inputRawZipPath, string outputRawZipPath, string modName, OutputHandlerDelegate outputDelegate = null)
{
+ ModOS currentOS = GetModOSOfRawZip(inputRawZipPath);
+ SendOutput("Zip Recognized as " + currentOS);
+
+ if (currentOS == ModOS.Mac)
+ {
+ SendOutput("Zip is already a raw Mac zip.");
+ return;
+ }
+
outputHandler = outputDelegate;
string baseTempDirectory = tmp + "/" + Path.GetFileNameWithoutExtension(inputRawZipPath);
string extractDirectory = baseTempDirectory + "/extract";
@@ -228,13 +295,27 @@ public abstract class RawMods : IMods
// Delete unnecessary files, rename data.win, move in the new runner
SendOutput("Delete unnecessary files for Mac and lowercase them...");
- File.Delete(extractDirectory + "/AM2R.exe");
- File.Delete(extractDirectory + "/D3DX9_43.dll");
- File.Move(extractDirectory + "/data.win", extractDirectory + "/game.ios");
+ switch (currentOS)
+ {
+ case ModOS.Windows:
+ File.Delete(assetsDir + "/AM2R.exe");
+ File.Delete(assetsDir + "/D3DX9_43.dll");
+ File.Move(assetsDir + "/data.win", assetsDir + "/game.ios");
+ break;
+ case ModOS.Linux:
+ File.Delete(assetsDir + "/runner");
+ HelperMethods.DirectoryCopy(assetsDir + "/assets", assetsDir);
+ Directory.Delete(assetsDir + "/assets", true);
+ File.Move(assetsDir + "/game.unx", assetsDir + "/game.ios");
+ break;
+ default: throw new NotSupportedException("The OS of the mod zip is unknown and thus not supported");
+ }
+
if (!File.Exists(assetsDir + "/icon.png"))
File.Copy(utilDir + "/icon.png", extractDirectory + "/icon.png");
if (!File.Exists(assetsDir + "/splash.png"))
File.Copy(utilDir + "/splash.png", 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"))
Directory.Delete(extractDirectory + "/lang/fonts", true);
@@ -243,7 +324,7 @@ public abstract class RawMods : IMods
HelperMethods.LowercaseFolder(extractDirectory);
// Convert data.win to BC16 and get rid of not needed functions anymore
- SendOutput("Editing data.win to change data.win BC version and functions...");
+ SendOutput("Editing data.win to change ByteCode version and functions...");
string bin;
string args;
@@ -274,7 +355,7 @@ public abstract class RawMods : IMods
// Copy assets to the place where they belong to
SendOutput("Copy files over...");
- HelperMethods.DirectoryCopy(extractDirectory, assetsDir, true);
+ HelperMethods.DirectoryCopy(extractDirectory, assetsDir);
// Edit config and plist to change display name
SendOutput("Editing Runner references to AM2R...");