Merge pull request #2 from Miepee/XML

XML Rewrite for the Modpacker
pull/3/head
Lojical 6 years ago committed by GitHub
commit a4a04c371e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -51,8 +51,14 @@
<ApplicationIcon>icon64.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=12.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
<Reference Include="Microsoft.WindowsAPICodePack, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.WindowsAPICodePack-Core.1.1.0.0\lib\Microsoft.WindowsAPICodePack.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.Shell, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.Shell.dll</HintPath>
</Reference>
<Reference Include="Microsoft.WindowsAPICodePack.ShellExtensions, Version=1.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>packages\Microsoft.WindowsAPICodePack-Shell.1.1.0.0\lib\Microsoft.WindowsAPICodePack.ShellExtensions.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
@ -68,15 +74,16 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ModProfile.cs" />
<Compile Include="ModPacker.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="ModPacker.Designer.cs">
<DependentUpon>ModPacker.cs</DependentUpon>
</Compile>
<Compile Include="XML\ModProfileXML.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="XML\Serializer.cs" />
<EmbeddedResource Include="ModPacker.resx">
<DependentUpon>ModPacker.cs</DependentUpon>
</EmbeddedResource>
@ -100,6 +107,9 @@
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<None Include="utilities\android\apktool.yml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="utilities\android\LICENSE">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
@ -131,5 +141,6 @@
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -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;
}
}

@ -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<ModProfileXML>(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())

@ -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;
}
}
}

@ -0,0 +1,60 @@
using System;
using System.Xml.Serialization;
namespace AM2R_ModPacker
{
/// <summary>
/// Class that handles how the modmeta settings are saved as XML.
/// </summary>
[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;
}
}
}

@ -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
{
/// <summary>
/// The <c>Serializer</c> class, that serializes to and deserializes from XML files.
/// </summary>
public class Serializer
{
/// <summary>
/// Serializes <paramref name="item"/> as a <typeparamref name="T"/> to XML.
/// </summary>
/// <typeparam name="T">The class to serialize to.</typeparam>
/// <param name="item">The object that will be serialized.</param>
/// <returns>The serialized XML as a <see cref="string"/>.</returns>
public static string Serialize<T>(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;
}
/// <summary>
/// Deserialize <paramref name="xmlString"/> into an object of class <typeparamref name="T"/> that can be assigned.
/// </summary>
/// <typeparam name="T">The class that <paramref name="xmlString"/> will be deserialized to.</typeparam>
/// <param name="xmlString">An XML <see cref="string"/> that will be deserialized.</param>
/// <returns>A deserialized object of class <typeparamref name="T"/> from <paramref name="xmlString"/>.</returns>
public static T Deserialize<T>(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);
}
}
}
}

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="12.0.3" targetFramework="net472" />
<package id="Microsoft.WindowsAPICodePack-Core" version="1.1.0.0" targetFramework="net472" />
<package id="Microsoft.WindowsAPICodePack-Shell" version="1.1.0.0" targetFramework="net472" />
</packages>

@ -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
Loading…
Cancel
Save