diff --git a/AM2RModPacker.csproj b/AM2RModPacker.csproj
index ff06b12..fc43b2b 100644
--- a/AM2RModPacker.csproj
+++ b/AM2RModPacker.csproj
@@ -51,8 +51,14 @@
icon64.ico
-
- packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll
+
+ packages\Microsoft.WindowsAPICodePack-Core.1.1.0.0\lib\Microsoft.WindowsAPICodePack.dll
+
+
+ packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.Shell.dll
+
+
+ packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.ShellExtensions.dll
@@ -68,15 +74,16 @@
-
Form
ModPacker.cs
+
+
ModPacker.cs
@@ -100,6 +107,9 @@
Settings.settings
True
+
+ PreserveNewest
+
PreserveNewest
@@ -131,5 +141,6 @@
false
+
\ No newline at end of file
diff --git a/ModPacker.Designer.cs b/ModPacker.Designer.cs
index 60bb452..ef9fdc6 100644
--- a/ModPacker.Designer.cs
+++ b/ModPacker.Designer.cs
@@ -42,12 +42,16 @@
this.NameTextBox = new System.Windows.Forms.TextBox();
this.label1 = new System.Windows.Forms.Label();
this.panel3 = new System.Windows.Forms.Panel();
+ this.LinuxCheckBox = new System.Windows.Forms.CheckBox();
+ this.WindowsCheckBox = new System.Windows.Forms.CheckBox();
this.ApkLabel = new System.Windows.Forms.Label();
this.ApkButton = new System.Windows.Forms.Button();
this.AndroidCheckBox = new System.Windows.Forms.CheckBox();
this.YYCCheckBox = new System.Windows.Forms.CheckBox();
this.SaveCheckBox = new System.Windows.Forms.CheckBox();
this.MusicCheckBox = new System.Windows.Forms.CheckBox();
+ this.CustomSaveDataButton = new System.Windows.Forms.Button();
+ this.SaveDirectoryLabel = new System.Windows.Forms.Label();
this.panel1.SuspendLayout();
this.panel2.SuspendLayout();
this.panel3.SuspendLayout();
@@ -175,6 +179,10 @@
//
// panel3
//
+ this.panel3.Controls.Add(this.SaveDirectoryLabel);
+ this.panel3.Controls.Add(this.CustomSaveDataButton);
+ this.panel3.Controls.Add(this.LinuxCheckBox);
+ this.panel3.Controls.Add(this.WindowsCheckBox);
this.panel3.Controls.Add(this.ApkLabel);
this.panel3.Controls.Add(this.ApkButton);
this.panel3.Controls.Add(this.AndroidCheckBox);
@@ -186,6 +194,30 @@
this.panel3.Size = new System.Drawing.Size(291, 111);
this.panel3.TabIndex = 2;
//
+ // LinuxCheckBox
+ //
+ this.LinuxCheckBox.AutoSize = true;
+ this.LinuxCheckBox.Location = new System.Drawing.Point(194, 66);
+ this.LinuxCheckBox.Name = "LinuxCheckBox";
+ this.LinuxCheckBox.Size = new System.Drawing.Size(51, 17);
+ this.LinuxCheckBox.TabIndex = 9;
+ this.LinuxCheckBox.Text = "Linux";
+ this.LinuxCheckBox.UseVisualStyleBackColor = true;
+ this.LinuxCheckBox.CheckedChanged += new System.EventHandler(this.LinuxCheckBox_CheckedChanged);
+ //
+ // WindowsCheckBox
+ //
+ this.WindowsCheckBox.AutoSize = true;
+ this.WindowsCheckBox.Checked = true;
+ this.WindowsCheckBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.WindowsCheckBox.Location = new System.Drawing.Point(194, 45);
+ this.WindowsCheckBox.Name = "WindowsCheckBox";
+ this.WindowsCheckBox.Size = new System.Drawing.Size(70, 17);
+ this.WindowsCheckBox.TabIndex = 8;
+ this.WindowsCheckBox.Text = "Windows";
+ this.WindowsCheckBox.UseVisualStyleBackColor = true;
+ this.WindowsCheckBox.CheckedChanged += new System.EventHandler(this.WindowsCheckBox_CheckedChanged);
+ //
// ApkLabel
//
this.ApkLabel.AutoSize = true;
@@ -210,7 +242,6 @@
// AndroidCheckBox
//
this.AndroidCheckBox.AutoSize = true;
- this.AndroidCheckBox.Enabled = false;
this.AndroidCheckBox.Location = new System.Drawing.Point(4, 66);
this.AndroidCheckBox.Name = "AndroidCheckBox";
this.AndroidCheckBox.Size = new System.Drawing.Size(107, 17);
@@ -232,17 +263,18 @@
// SaveCheckBox
//
this.SaveCheckBox.AutoSize = true;
- this.SaveCheckBox.Location = new System.Drawing.Point(4, 24);
+ this.SaveCheckBox.Location = new System.Drawing.Point(4, 3);
this.SaveCheckBox.Name = "SaveCheckBox";
this.SaveCheckBox.Size = new System.Drawing.Size(163, 17);
this.SaveCheckBox.TabIndex = 3;
this.SaveCheckBox.Text = "Uses custom savedata folder";
this.SaveCheckBox.UseVisualStyleBackColor = true;
+ this.SaveCheckBox.CheckedChanged += new System.EventHandler(this.SaveCheckBox_CheckedChanged);
//
// MusicCheckBox
//
this.MusicCheckBox.AutoSize = true;
- this.MusicCheckBox.Location = new System.Drawing.Point(4, 3);
+ this.MusicCheckBox.Location = new System.Drawing.Point(4, 24);
this.MusicCheckBox.Margin = new System.Windows.Forms.Padding(2, 3, 3, 3);
this.MusicCheckBox.Name = "MusicCheckBox";
this.MusicCheckBox.Size = new System.Drawing.Size(117, 17);
@@ -250,6 +282,28 @@
this.MusicCheckBox.Text = "Uses custom music";
this.MusicCheckBox.UseVisualStyleBackColor = true;
//
+ // CustomSaveDataButton
+ //
+ this.CustomSaveDataButton.Enabled = false;
+ this.CustomSaveDataButton.Location = new System.Drawing.Point(194, 3);
+ this.CustomSaveDataButton.Name = "CustomSaveDataButton";
+ this.CustomSaveDataButton.Size = new System.Drawing.Size(77, 19);
+ this.CustomSaveDataButton.TabIndex = 10;
+ this.CustomSaveDataButton.Text = "Select folder";
+ this.CustomSaveDataButton.UseVisualStyleBackColor = true;
+ this.CustomSaveDataButton.Click += new System.EventHandler(this.CustomSaveDataButton_Click);
+ //
+ // SaveDirectoryLabel
+ //
+ this.SaveDirectoryLabel.AutoSize = true;
+ this.SaveDirectoryLabel.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.SaveDirectoryLabel.Location = new System.Drawing.Point(118, 25);
+ this.SaveDirectoryLabel.Name = "SaveDirectoryLabel";
+ this.SaveDirectoryLabel.Size = new System.Drawing.Size(87, 13);
+ this.SaveDirectoryLabel.TabIndex = 11;
+ this.SaveDirectoryLabel.Text = "SaveDirectory";
+ this.SaveDirectoryLabel.Visible = false;
+ //
// ModPacker
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
@@ -296,6 +350,10 @@
private System.Windows.Forms.CheckBox MusicCheckBox;
private System.Windows.Forms.Label ApkLabel;
private System.Windows.Forms.Label CreateLabel;
+ private System.Windows.Forms.CheckBox LinuxCheckBox;
+ private System.Windows.Forms.CheckBox WindowsCheckBox;
+ private System.Windows.Forms.Button CustomSaveDataButton;
+ private System.Windows.Forms.Label SaveDirectoryLabel;
}
}
diff --git a/ModPacker.cs b/ModPacker.cs
index 635ce65..476e6b9 100644
--- a/ModPacker.cs
+++ b/ModPacker.cs
@@ -11,7 +11,8 @@ using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;
-using Newtonsoft.Json;
+using Microsoft.WindowsAPICodePack.Dialogs;
+using System.Text.RegularExpressions;
namespace AM2R_ModPacker
{
@@ -20,12 +21,13 @@ namespace AM2R_ModPacker
private static readonly string ORIGINAL_MD5 = "f2b84fe5ba64cb64e284be1066ca08ee";
private bool isOriginalLoaded, isModLoaded, isApkLoaded;
private string localPath, originalPath, modPath, apkPath;
- private static readonly string[] DATAFILES_BLACKLIST = { "data.win", "AM2R.exe", "D3DX9_43.dll" };
- private ModProfile profile;
+ private static readonly string[] DATAFILES_BLACKLIST = { "data.win", "AM2R.exe", "D3DX9_43.dll", "game.unx" };
+ private static string saveFilePath = null;
+ private ModProfileXML profile;
public ModPacker()
{
InitializeComponent();
- profile = new ModProfile(1, "", "", false, "default", false, false);
+ profile = new ModProfileXML(1, "", "", false, "default", false, false, "path"); // (1, "", "", false, "default", false, false);
isOriginalLoaded = false;
isModLoaded = false;
isApkLoaded = false;
@@ -63,7 +65,7 @@ namespace AM2R_ModPacker
string output;
- if (profile.name == "" || profile.author == "")
+ if (profile.Name == "" || profile.Author == "")
{
MessageBox.Show("Text field missing! Mod packaging aborted.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
@@ -144,19 +146,27 @@ namespace AM2R_ModPacker
}
// Create AM2R.exe and data.win patches
- if (profile.usesYYC)
+ if (profile.OperatingSystem == "Windows")
{
- CreatePatch(tempOriginalPath + "\\data.win", tempModPath + "\\AM2R.exe", tempProfilePath + "\\AM2R.xdelta");
+ if (profile.UsesYYC)
+ {
+ CreatePatch(tempOriginalPath + "\\data.win", tempModPath + "\\AM2R.exe", tempProfilePath + "\\AM2R.xdelta");
+ }
+ else
+ {
+ CreatePatch(tempOriginalPath + "\\data.win", tempModPath + "\\data.win", tempProfilePath + "\\data.xdelta");
+
+ CreatePatch(tempOriginalPath + "\\AM2R.exe", tempModPath + "\\AM2R.exe", tempProfilePath + "\\AM2R.xdelta");
+ }
}
- else
+ else if (profile.OperatingSystem == "Linux")
{
- CreatePatch(tempOriginalPath + "\\data.win", tempModPath + "\\data.win", tempProfilePath + "\\data.xdelta");
-
- CreatePatch(tempOriginalPath + "\\AM2R.exe", tempModPath + "\\AM2R.exe", tempProfilePath + "\\AM2R.xdelta");
+ CreatePatch(tempOriginalPath + "\\data.win", tempModPath + "\\assets\\game.unx", tempProfilePath + "\\game.xdelta");
+ CreatePatch(tempOriginalPath + "\\AM2R.exe", tempModPath + "\\AM2R", tempProfilePath + "\\AM2R.xdelta");
}
// Create game.droid patch and wrapper if Android is supported
- if (profile.android)
+ if (profile.Android)
{
string tempAndroid = Directory.CreateDirectory(tempPath + "\\android").FullName;
@@ -240,15 +250,23 @@ namespace AM2R_ModPacker
proc.WaitForExit();
}
+ string tempAndroidProfilePath = tempProfilePath + "\\android";
+ Directory.CreateDirectory(tempAndroidProfilePath);
+
+ File.Move(tempProfilePath + "\\AM2RWrapper.apk", tempAndroidProfilePath + "\\AM2RWrapper.apk");
+ File.Move(tempProfilePath + "\\AM2R.ini", tempAndroidProfilePath + "\\AM2R.ini");
+ File.Move(localPath + "\\utilities\\android\\apktool.yml", tempAndroidProfilePath + "\\apktool.yml");
}
// Copy datafiles (exclude .ogg if custom music is not selected)
DirectoryInfo dinfo = new DirectoryInfo(tempModPath);
+ if (profile.OperatingSystem == "Linux")
+ dinfo = new DirectoryInfo(tempModPath + "\\assets");
Directory.CreateDirectory(tempProfilePath + "\\files_to_copy");
- if (profile.usesCustomMusic)
+ if (profile.UsesCustomMusic)
{
// Copy files, excluding the blacklist
CopyFilesRecursive(dinfo, DATAFILES_BLACKLIST, tempProfilePath + "\\files_to_copy");
@@ -258,16 +276,20 @@ namespace AM2R_ModPacker
// Get list of 1.1's music files
string[] musFiles = Directory.GetFiles(tempOriginalPath, "*.ogg").Select(file => Path.GetFileName(file)).ToArray();
+ if (profile.OperatingSystem == "Linux")
+ musFiles = Directory.GetFiles(tempOriginalPath, "*.ogg").Select(file => Path.GetFileName(file).ToLower()).ToArray();
+
+
// Combine musFiles with the known datafiles for a blacklist
string[] blacklist = musFiles.Concat(DATAFILES_BLACKLIST).ToArray();
// Copy files, excluding the blacklist
CopyFilesRecursive(dinfo, blacklist, tempProfilePath + "\\files_to_copy");
- }
+ }
// Export profile as JSON
- string jsonOutput = JsonConvert.SerializeObject(profile);
- File.WriteAllText(tempProfilePath + "\\modmeta.json", jsonOutput);
+ string xmlOutput = Serializer.Serialize(profile); ;// JsonConvert.SerializeObject(profile);
+ File.WriteAllText(tempProfilePath + "\\profile.xml", xmlOutput);
// Compress temp folder to .zip
if (File.Exists(output))
@@ -299,22 +321,38 @@ namespace AM2R_ModPacker
UpdateCreateButton();
}
+ private void WindowsCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ LinuxCheckBox.Checked = !WindowsCheckBox.Checked;
+ }
+
+ private void LinuxCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ WindowsCheckBox.Checked = !LinuxCheckBox.Checked;
+ }
+
+ private void SaveCheckBox_CheckedChanged(object sender, EventArgs e)
+ {
+ CustomSaveDataButton.Enabled = SaveCheckBox.Checked;
+ }
+
#endregion
private void LoadProfileParameters()
{
- profile.name = NameTextBox.Text;
- profile.author = AuthorTextBox.Text;
- profile.usesCustomMusic = MusicCheckBox.Checked;
- profile.usesYYC = YYCCheckBox.Checked;
- profile.android = AndroidCheckBox.Checked;
- if (SaveCheckBox.Checked)
+ profile.Name = NameTextBox.Text;
+ profile.Author = AuthorTextBox.Text;
+ profile.UsesCustomMusic = MusicCheckBox.Checked;
+ profile.UsesYYC = YYCCheckBox.Checked;
+ profile.Android = AndroidCheckBox.Checked;
+ profile.OperatingSystem = WindowsCheckBox.Checked ? "Windows" : "Linux";
+ if (SaveCheckBox.Checked && saveFilePath != null)
{
- profile.saveLocation = "custom";
+ profile.SaveLocation = saveFilePath;
}
else
{
- profile.saveLocation = "default";
+ profile.SaveLocation = "default";
}
}
@@ -327,12 +365,14 @@ namespace AM2R_ModPacker
originalPath = "";
modPath = "";
apkPath = "";
+ saveFilePath = null;
// Set labels
CreateLabel.Text = "Mod packaging aborted!";
OriginalLabel.Visible = false;
ModLabel.Visible = false;
ApkLabel.Visible = false;
+ SaveDirectoryLabel.Visible = false;
// Remove temp directory
if (Directory.Exists(Path.GetTempPath() + "\\AM2RModPacker"))
@@ -341,6 +381,38 @@ namespace AM2R_ModPacker
}
}
+ private void CustomSaveDataButton_Click(object sender, EventArgs e)
+ {
+ bool wasSuccessfull = false;
+ Regex saveRegex = new Regex(@"C:\\Users\\.*\\AppData\\Local\\"); //this is to ensure, that the save directory is valid. so far, this is only important for windows
+
+ // we either use this nuget package. Or we choose a very bad native solution. Went for nuget instead.
+ CommonOpenFileDialog dialog = new CommonOpenFileDialog();
+ dialog.InitialDirectory = Environment.GetEnvironmentVariable("LocalAppData");
+ dialog.IsFolderPicker = true;
+ while (!wasSuccessfull)
+ {
+ if (dialog.ShowDialog() == CommonFileDialogResult.Ok)
+ {
+ Match match = saveRegex.Match(dialog.FileName);
+ if (match.Success == false)
+ MessageBox.Show("Invalid Save Directory! Please choose one in %LocalAppData%");
+ else
+ {
+ wasSuccessfull = true;
+ saveFilePath = dialog.FileName.Replace(match.Value, "%LOCALAPPDATA%");
+ }
+ }
+ else
+ {
+ wasSuccessfull = true;
+ saveFilePath = null;
+ }
+ }
+ SaveDirectoryLabel.Visible = wasSuccessfull;
+ SaveDirectoryLabel.Text = saveFilePath;
+ }
+
private void CopyFilesRecursive(DirectoryInfo source, string[] blacklist, string destination)
{
foreach (FileInfo file in source.GetFiles())
diff --git a/ModProfile.cs b/ModProfile.cs
deleted file mode 100644
index f3ca61c..0000000
--- a/ModProfile.cs
+++ /dev/null
@@ -1,23 +0,0 @@
-namespace AM2R_ModPacker
-{
- internal class ModProfile
- {
- public int version { get; set; }
- public string name { get; set; }
- public string author { get; set; }
- public bool usesCustomMusic { get; set; }
- public string saveLocation { get; set; }
- public bool android { get; set; }
- public bool usesYYC { get; set; }
- public ModProfile(int version, string name, string author, bool usesCustomMusic, string saveLocation, bool android, bool usesYYC)
- {
- this.version = version;
- this.name = name;
- this.author = author;
- this.usesCustomMusic = usesCustomMusic;
- this.saveLocation = saveLocation;
- this.android = android;
- this.usesYYC = usesYYC;
- }
- }
-}
diff --git a/XML/ModProfileXML.cs b/XML/ModProfileXML.cs
new file mode 100644
index 0000000..b50bd0a
--- /dev/null
+++ b/XML/ModProfileXML.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Xml.Serialization;
+
+namespace AM2R_ModPacker
+{
+ ///
+ /// Class that handles how the modmeta settings are saved as XML.
+ ///
+ [Serializable]
+ [XmlRoot("message")]
+ public class ModProfileXML
+ {
+ [XmlAttribute("Version")]
+ public decimal Version
+ { get; set; }
+
+ [XmlAttribute("Name")]
+ public string Name
+ { get; set; }
+
+ [XmlAttribute("Author")]
+ public string Author
+ { get; set; }
+
+ [XmlAttribute("UsesCustomMusic")]
+ public bool UsesCustomMusic
+ { get; set; }
+
+ [XmlAttribute("SaveLocation")]
+ public string SaveLocation
+ { get; set; }
+
+ [XmlAttribute("SupportsAndroid")]
+ public bool Android
+ { get; set; }
+
+ [XmlAttribute("UsesYYC")]
+ public bool UsesYYC
+ { get; set; }
+
+ [XmlAttribute("OperatingSystem")]
+ public string OperatingSystem
+ { get; set; }
+
+ public ModProfileXML()
+ { }
+
+ public ModProfileXML(decimal version, string name, string author, bool usesCustomMusic, string saveLocation, bool android, bool usesYYC, string operatingSystem)
+ {
+ Version = version;
+ Name = name;
+ Author = author;
+ UsesCustomMusic = usesCustomMusic;
+ SaveLocation = saveLocation;
+ Android = android;
+ UsesYYC = usesYYC;
+ OperatingSystem = operatingSystem;
+ }
+ }
+}
diff --git a/XML/Serializer.cs b/XML/Serializer.cs
new file mode 100644
index 0000000..4053890
--- /dev/null
+++ b/XML/Serializer.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Runtime.Serialization;
+using System.Web;
+using System.Text;
+
+namespace AM2R_ModPacker
+{
+ ///
+ /// The Serializer class, that serializes to and deserializes from XML files.
+ ///
+ public class Serializer
+ {
+ ///
+ /// Serializes as a to XML.
+ ///
+ /// The class to serialize to.
+ /// The object that will be serialized.
+ /// The serialized XML as a .
+ public static string Serialize(object item)
+ {
+ Type t = typeof(T);
+ MemoryStream memStream = new MemoryStream();
+ System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(t);
+
+ serializer.Serialize(memStream, item);
+
+ string xml = Encoding.UTF8.GetString(memStream.ToArray());
+
+ memStream.Flush();
+ memStream.Close();
+ memStream.Dispose();
+ memStream = null;
+
+ return xml;
+ }
+
+ ///
+ /// Deserialize into an object of class that can be assigned.
+ ///
+ /// The class that will be deserialized to.
+ /// An XML that will be deserialized.
+ /// A deserialized object of class from .
+ public static T Deserialize(string xmlString)
+ {
+ Type t = typeof(T);
+ using (MemoryStream memStream = new MemoryStream(Encoding.UTF8.GetBytes(xmlString)))
+ {
+ System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(t);
+ return (T)serializer.Deserialize(memStream);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/packages.config b/packages.config
index a9de8b5..d469167 100644
--- a/packages.config
+++ b/packages.config
@@ -1,4 +1,5 @@
-
+
+
\ No newline at end of file
diff --git a/utilities/android/apktool.yml b/utilities/android/apktool.yml
new file mode 100644
index 0000000..0a1dac5
--- /dev/null
+++ b/utilities/android/apktool.yml
@@ -0,0 +1,24 @@
+!!brut.androlib.meta.MetaInfo
+apkFileName: AM2RWrapper.apk
+compressionType: false
+doNotCompress:
+- resources.arsc
+- ogg
+isFrameworkApk: false
+packageInfo:
+ forcedPackageId: '127'
+ renameManifestPackage: null
+sdkInfo:
+ minSdkVersion: '9'
+ targetSdkVersion: '23'
+sharedLibrary: false
+sparseResources: true
+unknownFiles: {}
+usesFramework:
+ ids:
+ - 1
+ tag: null
+version: 2.5.0
+versionInfo:
+ versionCode: '1005012'
+ versionName: 1.5.2