Skip to content
This repository has been archived by the owner on Jan 6, 2022. It is now read-only.

Commit

Permalink
Draft of archive export method
Browse files Browse the repository at this point in the history
  • Loading branch information
REHERC committed Apr 16, 2021
1 parent 7c7cccc commit 8e349f9
Show file tree
Hide file tree
Showing 15 changed files with 177 additions and 11 deletions.
2 changes: 2 additions & 0 deletions App.AdventureMaker.Core/App.AdventureMaker.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<None Remove="Resources\Images\StatusError.png" />
<None Remove="Resources\Images\StatusInfo.png" />
<None Remove="Resources\Images\StatusWarning.png" />
<None Remove="Resources\Text\archive_readme.txt" />
</ItemGroup>

<ItemGroup>
Expand All @@ -33,6 +34,7 @@
<EmbeddedResource Include="Resources\Images\StatusError.png" />
<EmbeddedResource Include="Resources\Images\StatusInfo.png" />
<EmbeddedResource Include="Resources\Images\StatusWarning.png" />
<EmbeddedResource Include="Resources\Text\archive_readme.txt" />
</ItemGroup>

<ItemGroup>
Expand Down
22 changes: 20 additions & 2 deletions App.AdventureMaker.Core/Commands/ExportFileCommand.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
using App.AdventureMaker.Core.Interfaces;
using App.AdventureMaker.Core.Forms.FileChecker;
using App.AdventureMaker.Core.Interfaces;
using Distance.AdventureMaker.Common.Enums;
using Distance.AdventureMaker.Common.Models;
using Distance.AdventureMaker.Common.Validation.Validators;
using Eto.Forms;
using System;
using System.IO;
using static Constants;
using static Dialogs;

namespace App.AdventureMaker.Core.Commands
Expand Down Expand Up @@ -29,7 +34,20 @@ protected override void OnExecuted(EventArgs e)
{
if (dialog.ShowDialog(null) == DialogResult.Ok)
{
MessageBox.Show("Unimplemented :(");
CampaignValidator validator = new CampaignValidator(editor.CurrentFile.Directory);
validator.Validate(editor.Document);

if (validator.GetMessages(StatusLevel.Error).Length > 0)
{
new FileCheckWindow(validator)
{
Title = DIALOG_CAPTION_EXPORT_CANCELED
}.Show();
}
else
{
}
Project.ExportProject(new FileInfo(dialog.FileName), editor);
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions App.AdventureMaker.Core/Global/Constants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
using System;
using System.Collections.Generic;

public static partial class Constants
public static class Constants
{
public const string STEAM_APPID_FILE = "steam_appid.txt";
public const string DISTANCE_STEAM_APPID = "233610";
Expand All @@ -22,7 +22,7 @@ public static partial class Constants

// Tool-specific filters
public const string DIALOG_FILTER_PROJECT = "Json project files (project.json)|project.json";
public const string DIALOG_FILTER_ARCHIVE = "Extension description|*";
public const string DIALOG_FILTER_ARCHIVE = "Campaign Resource Assed Bundle (.crab)|*.crab";

// Image filters
public const string DIALOG_FILTER_PNG = "Portable Network Graphics (*.png)|*.png";
Expand Down Expand Up @@ -54,6 +54,7 @@ public static partial class Constants
public const string DIALOG_CAPTION_REMOVE_RESOURCE = "Remove resource";
public const string DIALOG_CAPTION_START_PREVIEW = "Preview mode";
public const string DIALOG_CAPTION_MISSING_FILE = "Missing file";
public const string DIALOG_CAPTION_EXPORT_CANCELED = "Export canceled!";

public const string PLAYLIST_NO_NAME = "(No playlist name)";

Expand Down
82 changes: 81 additions & 1 deletion App.AdventureMaker.Core/Global/Project.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
using App.AdventureMaker.Core.Interfaces;
#pragma warning disable IDE0063
using App.AdventureMaker.Core.Interfaces;
using Distance.AdventureMaker.Common.Models;
using Distance.AdventureMaker.Common.Models.Resources;
using Distance.AdventureMaker.Common.Models.UI;
using Newtonsoft.Json;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Writers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;

namespace App.AdventureMaker.Core
{
Expand Down Expand Up @@ -34,7 +42,79 @@ public static CampaignFile CreateProject(ProjectCreateData data)

public static void ExportProject(FileInfo destination, IEditor<CampaignFile> editor)
{
// Just testing...
/*using (Stream file = File.Create(destination.FullName))
{
using (IWriter archive = WriterFactory.Open(file, ArchiveType.Zip, CompressionType.LZMA))
{
archive.CreateEntry("project.json", JsonConvert.SerializeObject(editor.Document));
}
}*/

Dictionary<string, string> hashes = new Dictionary<string, string>();

using (HashAlgorithm ha = SHA512.Create())
{
void hash(string resource)
{
FileInfo file = editor.GetResourceFile(resource);
if (hashes.ContainsKey(resource) || !file.Exists) return;

using (Stream stream = File.OpenRead(file.FullName))
{
byte[] hashed = ha.ComputeHash(stream);
hashes[resource] = BitConverter.ToString(hashed).Replace("-", "");
}
}

foreach (CampaignResource resource in editor.Document.Data.Resources)
{
switch (resource)
{
case CampaignResource.Texture texture:
hash(texture.file);
break;
case CampaignResource.Level level:
hash(level.file);
hash(level.thumbnail);
break;
}
}
}

using (Stream file = File.Create(destination.FullName))
{
using (ZipArchive archive = ZipArchive.Create())
{
archive.AddEntry("readme.txt", Resources.GetText("archive_readme.txt").GetStream());
archive.AddEntry("project.json", JsonConvert.SerializeObject(editor.Document).GetStream());
archive.AddEntry("hashes.json", JsonConvert.SerializeObject(hashes).GetStream());

void addfile(string resource)
{
FileInfo file = editor.GetResourceFile(resource);
if (!file.Exists) return;

archive.AddEntry($"resources/{resource}", File.OpenRead(file.FullName));
}

foreach (CampaignResource resource in editor.Document.Data.Resources)
{
switch (resource)
{
case CampaignResource.Texture texture:
addfile(texture.file);
break;
case CampaignResource.Level level:
addfile(level.file);
addfile(level.thumbnail);
break;
}
}

archive.SaveTo(file);
}
}
}
}
}
8 changes: 8 additions & 0 deletions App.AdventureMaker.Core/Resources/Text/archive_readme.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
Custom Campaign V2.0

This file was built using the custom campaign community tools for Distance:
It is not advised to manually edit this file as it could break in unpredictable ways

For more info, refer to
- The distance mods project page: https://github.com/REHERC/Centrifuge.Mods.Distance
- The distance discord server: http://discord.gg/distance
1 change: 1 addition & 0 deletions Centrifuge.Mods.Distance.sln
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ Global
Repository.Metadata\Repository.Metadata.projitems*{af094e78-872d-4473-9c5f-063c6640f94e}*SharedItemsImports = 13
Distance.CustomCar.Content\Distance.CustomCar.Content.projitems*{b250cc3f-e2f1-40e6-8a89-5ad23d54c019}*SharedItemsImports = 13
Common.Distance.AdventureMaker\Common.Distance.AdventureMaker.projitems*{b3f55581-78bd-4ba4-bb36-d80f3716dbe4}*SharedItemsImports = 4
Common.Extensions\Common.Extensions.projitems*{b3f55581-78bd-4ba4-bb36-d80f3716dbe4}*SharedItemsImports = 4
Common.Json\Common.Json.projitems*{b3f55581-78bd-4ba4-bb36-d80f3716dbe4}*SharedItemsImports = 4
Common.SharpCompress\Common.SharpCompress.projitems*{b3f55581-78bd-4ba4-bb36-d80f3716dbe4}*SharedItemsImports = 4
Distance.AdventureMaker.Content\Distance.AdventureMaker.Content.projitems*{b6eca462-ea0b-4bd3-8419-2a59f1db34ed}*SharedItemsImports = 13
Expand Down
1 change: 1 addition & 0 deletions Common.Extensions/Common.Extensions.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@
<Compile Include="$(MSBuildThisFileDirectory)mscorlib\System\IO\FileInfoEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)mscorlib\System\IO\DirectoryInfoEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)mscorlib\System\IO\IO.cs" />
<Compile Include="$(MSBuildThisFileDirectory)mscorlib\System\StringEx.cs" />
</ItemGroup>
</Project>
4 changes: 2 additions & 2 deletions Common.Extensions/mscorlib/System/IO/DirectoryInfoEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@ public static bool FileExistsInside(this DirectoryInfo directory, FileInfo file,
// Example: C:\ABC\DEF => 3 | C:\ABC\DEF\GHI\JKL => 5
public static int GetFolderLength(this DirectoryInfo directory)
{
return directory.FullName.Split(GetSeparatorChars()).Count(item => !string.IsNullOrWhiteSpace(item));
return directory.FullName.Split(GetSeparatorChars()).Count(item => !string.IsNullOrEmpty(item));
}

// Returns a string representing a folder path with its beginning n folders "cut" from the string
// Example: C:\ABC\DEF\GHI;2 => DEF\GHI
public static string CutFolderStart(this DirectoryInfo directory, int cut)
{
return string.Join(Path.DirectorySeparatorChar, directory.FullName.Split(GetSeparatorChars()).Skip(cut));
return string.Join("" + Path.DirectorySeparatorChar, directory.FullName.Split(GetSeparatorChars()).Skip(cut).ToArray());
}

public static void CreateIfDoesntExist(this DirectoryInfo directory)
Expand Down
4 changes: 2 additions & 2 deletions Common.Extensions/mscorlib/System/IO/FileInfoEx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@ public static class FileInfoEx
// Example: C:\ABC\DEF.txt => 3 | C:\ABC\DEF\GHI\JKL.txt => 5
public static int GetFolderLength(this FileInfo file)
{
return file.FullName.Split(GetSeparatorChars()).Count(item => !string.IsNullOrWhiteSpace(item));
return file.FullName.Split(GetSeparatorChars()).Count(item => !string.IsNullOrEmpty(item));
}

// Returns a string representing a folder path with its beginning n folders "cut" from the string
// Example: C:\ABC\DEF\GHI.txt;2 => DEF\GHI.txt
public static string CutFolderStart(this FileInfo file, int cut)
{
return string.Join(Path.DirectorySeparatorChar, file.FullName.Split(GetSeparatorChars()).Skip(cut));
return string.Join("" + Path.DirectorySeparatorChar, file.FullName.Split(GetSeparatorChars()).Skip(cut).ToArray());
}

public static bool PathEquals(this FileInfo file, FileInfo other)
Expand Down
12 changes: 12 additions & 0 deletions Common.Extensions/mscorlib/System/StringEx.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma warning disable RCS1110

using System.IO;
using System.Text;

public static class StringEx
{
public static Stream GetStream(this string input)
{
return new MemoryStream(Encoding.UTF8.GetBytes(input));
}
}
2 changes: 2 additions & 0 deletions Common.SharpCompress/Common.SharpCompress.projitems
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
<Import_RootNamespace>Common.SharpCompress</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Extensions\SharpCompress\Archives\Zip\ZipArchiveEntryEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Extensions\SharpCompress\Writers\IWriterEx.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Harmony\SharpCompress\Common\ArchiveEncoding\ctor.cs" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#pragma warning disable RCS1110, IDE0063
using SharpCompress.Archives.Zip;
using System.IO;

public static class ZipArchiveEntryEx
{
public static string GetText(this ZipArchiveEntry entry)
{
using (StreamReader reader = new StreamReader(entry.OpenEntryStream()))
{
return reader.ReadToEnd();
}
}
}
15 changes: 15 additions & 0 deletions Common.SharpCompress/Extensions/SharpCompress/Writers/IWriterEx.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#pragma warning disable RCS1110, IDE0063

using SharpCompress.Writers;
using System.IO;

public static class IWriterEx
{
public static void CreateEntry(this IWriter writer, string filename, string data)
{
using (Stream stream = data.GetStream())
{
writer.Write(filename, stream);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,25 @@

namespace Common.SharpCompress.Harmony
{
/* This patch is required for the following reasons:
* When running distance, the game runs with modo which is basically .Net 3.5
* The thing is that the default encoding for the archives is a special one (CodePage 437)
* And this special encoding isn't present in mono
* Basically this patch avoids crashes
*
* To be sure files are both written and read the same way,
* the patch is also applied to the tool itself
*
* See this link for more info https://gist.github.com/REHERC/e6ac069bf52659a02b6042604d4c166d
*/
[HarmonyPatch(typeof(ArchiveEncoding), MethodType.Constructor)]
internal static class SharpCompress__Common__ArchiveEncoding___ctor__Patch
{
[HarmonyPrefix]
internal static bool Prefix(ArchiveEncoding __instance)
{
__instance.Default = __instance.Password = Encoding.Unicode;

// Use UTF-8 so 7-zip can read the arcvhive (unicode is unsupported)
__instance.Default = __instance.Password = Encoding.UTF8;
return false;
}
}
Expand Down
1 change: 1 addition & 0 deletions Distance.AdventureMaker/Distance.AdventureMaker.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
<Import Project="..\Common.Distance.AdventureMaker\Common.Distance.AdventureMaker.projitems" Label="Shared" />
<Import Project="..\Common.Json\Common.Json.projitems" Label="Shared" />
<Import Project="..\Common.SharpCompress\Common.SharpCompress.projitems" Label="Shared" />
<Import Project="..\Common.Extensions\Common.Extensions.projitems" Label="Shared" />
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>SET MODNAME=Distance Adventure Maker
Expand Down

0 comments on commit 8e349f9

Please sign in to comment.