diff --git a/Runtime/Classes/EncodedImage.cs b/Runtime/Classes/EncodedImage.cs
new file mode 100644
index 0000000..ffe830e
--- /dev/null
+++ b/Runtime/Classes/EncodedImage.cs
@@ -0,0 +1,19 @@
+using UnityEngine;
+
+namespace ModIO
+{
+ public class EncodedImage
+ {
+ public string extension;
+ public byte[] data;
+
+ public static EncodedImage PNGFromTexture2D(Texture2D texture2D)
+ {
+ return new EncodedImage
+ {
+ extension = "png",
+ data = texture2D.EncodeToPNG()
+ };
+ }
+ }
+}
diff --git a/Runtime/Classes/EncodedImage.cs.meta b/Runtime/Classes/EncodedImage.cs.meta
new file mode 100644
index 0000000..57fb5a5
--- /dev/null
+++ b/Runtime/Classes/EncodedImage.cs.meta
@@ -0,0 +1,11 @@
+fileFormatVersion: 2
+guid: 629bf80cff7b9a64a94abd75a351d9df
+MonoImporter:
+ externalObjects: {}
+ serializedVersion: 2
+ defaultReferences: []
+ executionOrder: 0
+ icon: {instanceID: 0}
+ userData:
+ assetBundleName:
+ assetBundleVariant:
diff --git a/Runtime/Classes/ModProfileDetails.cs b/Runtime/Classes/ModProfileDetails.cs
index 1fde29b..42cbcf1 100644
--- a/Runtime/Classes/ModProfileDetails.cs
+++ b/Runtime/Classes/ModProfileDetails.cs
@@ -35,6 +35,11 @@ public class ModProfileDetails
///
#if UNITY_2019_4_OR_NEWER
public Texture2D logo;
+ ///
+ /// Logo encoded in supported format.
+ ///
+ ///
+ public EncodedImage encodedLogo;
#else
public byte[] logo;
#endif
@@ -45,6 +50,11 @@ public class ModProfileDetails
/// Can be null
#if UNITY_2019_4_OR_NEWER
public Texture2D[] images;
+ ///
+ /// Images encoded in supported format.
+ ///
+ ///
+ public IReadOnlyList encodedImages;
#else
public List images;
#endif
@@ -125,28 +135,44 @@ public class ModProfileDetails
/// Can be null
public CommunityOptions? communityOptions = CommunityOptions.AllowCommenting;
- internal byte[] GetLogo()
+ internal bool HasLogo()
+ {
+ return logo != null || encodedLogo != null;
+ }
+
+ internal EncodedImage GetLogo()
{
#if UNITY_2019_4_OR_NEWER
- // If a Texture2D type is not set to 'Sprite (2D or UI)' it will get flagged
- // by cloudflare as suspicious and be rejected. This will return a 403
- return logo.EncodeToPNG();
+ // If a Texture2D type is not set to 'Sprite (2D or UI)' it will get flagged
+ // by cloudflare as suspicious and be rejected. This will return a 403
+ if (encodedLogo == null)
+ encodedLogo = EncodedImage.PNGFromTexture2D(logo);
+ return encodedLogo;
#else
- return logo;
+ return logo;
#endif
}
-
+
+ internal bool HasGalleryImages()
+ {
+ return encodedImages != null || images != null;
+ }
+
internal List GetGalleryImages()
{
#if UNITY_2019_4_OR_NEWER
- List gallery = new List();
- foreach(var texture in images)
+ if (encodedImages == null)
{
- gallery.Add(texture.EncodeToPNG());
+ List gallery = new List();
+ foreach(var texture in images)
+ {
+ gallery.Add(EncodedImage.PNGFromTexture2D(texture));
+ }
+ encodedImages = gallery;
}
- return gallery;
+ return encodedImages;
#else
- return images;
+ return images;
#endif
}
}
diff --git a/Runtime/Classes/ModfileDetails.cs b/Runtime/Classes/ModfileDetails.cs
index f17970c..2327cbf 100644
--- a/Runtime/Classes/ModfileDetails.cs
+++ b/Runtime/Classes/ModfileDetails.cs
@@ -1,4 +1,6 @@
-namespace ModIO
+using System.IO;
+
+namespace ModIO
{
public class ModfileDetails
{
@@ -12,7 +14,13 @@ public class ModfileDetails
/// its contents will be compressed and uploaded when submitted via
/// ModIOUnity.UploadModfile.
///
- public string directory;
+ public string? directory;
+
+ ///
+ /// Compressed data to send.
+ /// Alternative to directory for creating mods in memory.
+ ///
+ public MemoryStream compressedDirectory
///
/// the changelog for this file version of the mod.
diff --git a/Runtime/ModIO.Implementation/Classes/CompressOperationMultiple.cs b/Runtime/ModIO.Implementation/Classes/CompressOperationMultiple.cs
index f01eb94..0b9656a 100644
--- a/Runtime/ModIO.Implementation/Classes/CompressOperationMultiple.cs
+++ b/Runtime/ModIO.Implementation/Classes/CompressOperationMultiple.cs
@@ -7,9 +7,9 @@ namespace ModIO.Implementation
{
internal class CompressOperationMultiple : CompressOperationBase
{
- public IEnumerable data;
+ public IEnumerable data;
- public CompressOperationMultiple(IEnumerable compressed, ProgressHandle progressHandle)
+ public CompressOperationMultiple(IEnumerable compressed, ProgressHandle progressHandle)
: base(progressHandle)
{
this.data = compressed;
@@ -31,11 +31,12 @@ public override async Task> Compress()
{
zipStream.SetLevel(3);
- foreach(var bytes in data)
+ foreach(var encodedImage in data)
{
- string entryName = $"image_{count}.png";
+ string entryName = $"image_{count}.{encodedImage.extension}";
count++;
+ byte[] bytes = encodedImage.data;
using(MemoryStream memoryStream = new MemoryStream())
{
memoryStream.Write(bytes, 0, bytes.Length);
diff --git a/Runtime/ModIO.Implementation/Classes/ModIOUnityImplementation.cs b/Runtime/ModIO.Implementation/Classes/ModIOUnityImplementation.cs
index 20898eb..b79ddf3 100644
--- a/Runtime/ModIO.Implementation/Classes/ModIOUnityImplementation.cs
+++ b/Runtime/ModIO.Implementation/Classes/ModIOUnityImplementation.cs
@@ -2005,7 +2005,7 @@ public static async Task EditModProfile(ModProfileDetails modDetails)
+ " The 'tags' array in the ModProfileDetails will be ignored.");
}
- var config = modDetails.logo != null
+ var config = modDetails.HasLogo()
? API.Requests.EditMod.RequestPOST(modDetails)
: API.Requests.EditMod.RequestPUT(modDetails);
@@ -2353,12 +2353,7 @@ public static async Task UploadModfile(ModfileDetails modfile)
if(IsInitialized(out result) && IsAuthenticatedSessionValid(out result)
&& IsModfileDetailsValid(modfile, out result))
{
- CompressOperationDirectory compressOperation = new CompressOperationDirectory(modfile.directory);
-
- Task> compressTask = compressOperation.Compress();
-
-
- var compressionTaskResult = await openCallbacks.Run(callbackConfirmation, compressTask);
+ var compressionTaskResult = await GetCompressedData(modfile, callbackConfirmation);
result = compressionTaskResult.result;
if(!result.Succeeded())
@@ -2370,9 +2365,6 @@ public static async Task UploadModfile(ModfileDetails modfile)
}
else
{
- Logger.Log(LogLevel.Verbose, $"Compressed file ({modfile.directory})"
- + $"\nstream length: {compressionTaskResult.value.Length}");
-
callbackConfirmation = openCallbacks.New();
var requestConfig = await API.Requests.AddModFile.Request(modfile, compressionTaskResult.value);
Task> task = WebRequestManager.Request(requestConfig, currentUploadHandle);
@@ -2399,6 +2391,23 @@ public static async Task UploadModfile(ModfileDetails modfile)
openCallbacks.Complete(callbackConfirmation);
return result;
+
+ static async Task> GetCompressedData(ModfileDetails modfile, TaskCompletionSource callbackConfirmation)
+ {
+ if(modfile.compressedDirectory != null) {
+ Logger.Log(LogLevel.Verbose, $"Using supplied MemoryStream of length: {modfile.compressedDirectory.Length}");
+ return ResultAnd.Create(ResultBuilder.Success, modfile.compressedDirectory);
+ }
+
+
+ CompressOperationDirectory compressOperation = new CompressOperationDirectory(modfile.directory);
+ Task> compressTask = compressOperation.Compress();
+
+ var compressionTaskResult = await openCallbacks.Run(callbackConfirmation, compressTask);
+ Logger.Log(LogLevel.Verbose, $"Compressed file ({modfile.directory})"
+ + $"\nstream length: {compressionTaskResult.value.Length}");
+ return compressionTaskResult;
+ }
}
public static async void UploadModMedia(ModProfileDetails modProfileDetails, Action callback)
@@ -2467,15 +2476,18 @@ public static async void ArchiveModProfile(ModId modId, Action callback)
static bool IsModfileDetailsValid(ModfileDetails modfile, out Result result)
{
- // Check directory exists
- if(!DataStorage.TryGetModfileDetailsDirectory(modfile.directory,
- out string notbeingusedhere))
+ if(modfile.compressedDirectory == null)
{
- Logger.Log(LogLevel.Error,
- "The provided directory in ModfileDetails could not be found or"
- + $" does not exist ({modfile.directory}).");
- result = ResultBuilder.Create(ResultCode.IO_DirectoryDoesNotExist);
- return false;
+ // Check directory exists
+ if(!DataStorage.TryGetModfileDetailsDirectory(modfile.directory,
+ out string _))
+ {
+ Logger.Log(LogLevel.Error,
+ "The provided directory in ModfileDetails could not be found or"
+ + $" does not exist ({modfile.directory}).");
+ result = ResultBuilder.Create(ResultCode.IO_DirectoryDoesNotExist);
+ return false;
+ }
}
// check metadata isn't too large
@@ -2504,8 +2516,8 @@ static bool IsModfileDetailsValid(ModfileDetails modfile, out Result result)
static bool IsModProfileDetailsValid(ModProfileDetails modDetails, out Result result)
{
- if(modDetails.logo == null || string.IsNullOrWhiteSpace(modDetails.summary)
- || string.IsNullOrWhiteSpace(modDetails.name))
+ if(!modDetails.HasLogo() || string.IsNullOrWhiteSpace(modDetails.summary)
+ || string.IsNullOrWhiteSpace(modDetails.name))
{
Logger.Log(
LogLevel.Error,
@@ -2530,9 +2542,9 @@ static bool IsModProfileDetailsValidForEdit(ModProfileDetails modDetails, out Re
return false;
}
- if(modDetails.logo != null)
+ if(modDetails.HasLogo())
{
- if(modDetails.logo.EncodeToPNG().Length > 8388608)
+ if(modDetails.GetLogo().data.Length > 8388608)
{
Logger.Log(LogLevel.Error,
"The provided logo in ModProfileDetails exceeds 8 megabytes");
diff --git a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddMod.cs b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddMod.cs
index 88a4702..a3832fd 100644
--- a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddMod.cs
+++ b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddMod.cs
@@ -37,8 +37,11 @@ public static WebRequestConfig Request(ModProfileDetails details)
}
}
- if(details.logo != null)
- request.AddField("logo","logo.png", details.GetLogo());
+ if(details.HasLogo())
+ {
+ var logo = details.GetLogo();
+ request.AddField("logo", $"logo.{logo.extension}", logo.data);
+ }
return request;
}
diff --git a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddModMedia.cs b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddModMedia.cs
index 1cdec78..e535d78 100644
--- a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddModMedia.cs
+++ b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/AddModMedia.cs
@@ -1,6 +1,5 @@
using System.IO;
using System.Threading.Tasks;
-using UnityEngine;
namespace ModIO.Implementation.API.Requests
{
@@ -15,13 +14,16 @@ public static async Task> Request(ModProfileDetails
ShouldRequestTimeout = false,
};
- if(details.logo != null)
- request.AddField("logo", "logo.png", details.logo.EncodeToPNG());
+ if(details.HasLogo())
+ {
+ var logo = details.GetLogo();
+ request.AddField("logo", $"logo.{logo.extension}", logo.data);
+ }
- if(details.images != null)
+ if(details.HasGalleryImages())
{
- var imageBytes = details.GetGalleryImages();
- CompressOperationMultiple zipOperation = new CompressOperationMultiple(imageBytes, null);
+ var encodedImages = details.GetGalleryImages();
+ CompressOperationMultiple zipOperation = new CompressOperationMultiple(encodedImages, null);
ResultAnd resultAnd = await zipOperation.Compress();
diff --git a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/EditMod.cs b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/EditMod.cs
index abf65ab..ebdaad8 100644
--- a/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/EditMod.cs
+++ b/Runtime/ModIO.Implementation/Implementation.API/Implementation.API.Requests/EditMod.cs
@@ -44,8 +44,11 @@ public static WebRequestConfig InternalRequest(ModProfileDetails details, string
request.AddField("metadata_blob", details.metadata);
- if(details.logo != null)
- request.AddField("logo", "logo.png", details.GetLogo());
+ if(details.HasLogo())
+ {
+ var logo = details.GetLogo();
+ request.AddField("logo", $"logo.{logo.extension}", logo.data);
+ }
return request;
}