Skip to content

Commit

Permalink
Full support for WebGL & Update README
Browse files Browse the repository at this point in the history
Signed-off-by: Bayu Satiyo <[email protected]>
  • Loading branch information
kiraio-moe committed Aug 8, 2023
1 parent c13bf5e commit 42cf178
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 154 deletions.
82 changes: 22 additions & 60 deletions BrotliUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,100 +4,62 @@ namespace USSR.Utilities
{
public class BrotliUtils
{
private static CompressionLevel GetCompressionLevel()
static CompressionLevel GetCompressionLevel()
{
if (Enum.IsDefined(typeof(CompressionLevel), 3)) // NOTE: CompressionLevel.SmallestSize == 3 is not supported in .NET Core 3.1
{
// NOTE: CompressionLevel.SmallestSize == 3 is not supported in .NET Core 3.1
if (Enum.IsDefined(typeof(CompressionLevel), 3))
return (CompressionLevel)3;
}

return CompressionLevel.Optimal;
}

public static byte[] CompressBytes(byte[] bytes) =>
CompressBytesAsync(bytes).GetAwaiter().GetResult();

public static async Task<byte[]> CompressBytesAsync(
byte[] bytes,
CancellationToken cancel = default
)
public static byte[] CompressBytes(byte[] bytes)
{
using MemoryStream? outputStream = new();
using (BrotliStream? compressionStream = new(outputStream, GetCompressionLevel()))
{
await compressionStream.WriteAsync(bytes, cancel);
}
compressionStream.Write(bytes);

return outputStream.ToArray();
}

public static void CompressFile(string originalFileName, string compressedFileName) =>
CompressFileAsync(originalFileName, compressedFileName).GetAwaiter().GetResult();

public static async Task CompressFileAsync(
string originalFileName,
string compressedFileName,
CancellationToken cancel = default
)
public static string CompressFile(string originalFileName, string compressedFileName)
{
using FileStream originalStream = File.Open(originalFileName, FileMode.Open);
using FileStream compressedStream = File.Create(compressedFileName);
await CompressStreamAsync(originalStream, compressedStream, cancel);
}
CompressStream(originalStream, compressedStream);

public static void CompressStream(Stream originalStream, Stream compressedStream) =>
CompressStreamAsync(originalStream, compressedStream).GetAwaiter().GetResult();
return compressedFileName;
}

public static async Task CompressStreamAsync(
Stream originalStream,
Stream compressedStream,
CancellationToken cancel = default
)
public static void CompressStream(Stream originalStream, Stream compressedStream)
{
using BrotliStream? compressor = new(compressedStream, GetCompressionLevel());
await originalStream.CopyToAsync(compressor, cancel);
originalStream.CopyTo(compressor);
}

public static byte[] DecompressBytes(byte[] bytes) =>
DecompressBytesAsync(bytes).GetAwaiter().GetResult();

public static async Task<byte[]> DecompressBytesAsync(
byte[] bytes,
CancellationToken cancel = default
)
public static byte[] DecompressBytes(byte[] bytes)
{
using MemoryStream? inputStream = new(bytes);
using MemoryStream outputStream = new();
using (BrotliStream compressionStream = new(inputStream, CompressionMode.Decompress))
{
await compressionStream.CopyToAsync(outputStream, cancel);
}
compressionStream.CopyTo(outputStream);

return outputStream.ToArray();
}

public static void DecompressFile(string compressedFileName, string outputFileName) =>
DecompressFileAsync(compressedFileName, outputFileName).GetAwaiter().GetResult();

public static async Task DecompressFileAsync(
string compressedFileName,
string outputFileName,
CancellationToken cancel = default
)
public static string DecompressFile(string compressedFileName, string outputFileName)
{
using FileStream compressedFileStream = File.Open(compressedFileName, FileMode.Open);
using FileStream outputFileStream = File.Create(outputFileName);
await DecompressStreamAsync(compressedFileStream, outputFileStream, cancel);
}
DecompressStream(compressedFileStream, outputFileStream);

public static void DecompressStream(Stream compressedStream, Stream outputStream) =>
DecompressStreamAsync(compressedStream, outputStream).GetAwaiter().GetResult();
return outputFileName;
}

public static async Task DecompressStreamAsync(
Stream compressedStream,
Stream outputStream,
CancellationToken cancel = default
)
public static void DecompressStream(Stream compressedStream, Stream outputStream)
{
using BrotliStream decompressor = new(compressedStream, CompressionMode.Decompress);
await decompressor.CopyToAsync(outputStream, cancel);
decompressor.CopyTo(outputStream);
}
}
}
Expand Down
80 changes: 21 additions & 59 deletions GZipUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,98 +6,60 @@ public class GZipUtils
{
private static CompressionLevel GetCompressionLevel()
{
if (Enum.IsDefined(typeof(CompressionLevel), 3)) // NOTE: CompressionLevel.SmallestSize == 3 is not supported in .NET Core 3.1 but is in .NET 6
{
// NOTE: CompressionLevel.SmallestSize == 3 is not supported in .NET Core 3.1 but is in .NET 6
if (Enum.IsDefined(typeof(CompressionLevel), 3))
return (CompressionLevel)3;
}

return CompressionLevel.Optimal;
}

public static byte[] CompressBytes(byte[] bytes) =>
CompressBytesAsync(bytes).GetAwaiter().GetResult();

public static async Task<byte[]> CompressBytesAsync(
byte[] bytes,
CancellationToken cancel = default
)
public static byte[] CompressBytes(byte[] bytes)
{
using MemoryStream? outputStream = new();
using (GZipStream? compressionStream = new(outputStream, GetCompressionLevel()))
{
await compressionStream.WriteAsync(bytes, cancel);
}
compressionStream.Write(bytes);

return outputStream.ToArray();
}

public static void CompressFile(string originalFileName, string compressedFileName) =>
CompressFileAsync(originalFileName, compressedFileName).GetAwaiter().GetResult();

public static async Task CompressFileAsync(
string originalFileName,
string compressedFileName,
CancellationToken cancel = default
)
public static string CompressFile(string originalFileName, string compressedFileName)
{
using FileStream originalStream = File.Open(originalFileName, FileMode.Open);
using FileStream compressedStream = File.Create(compressedFileName);
await CompressStreamAsync(originalStream, compressedStream, cancel);
}
CompressStream(originalStream, compressedStream);

public static void CompressStream(Stream originalStream, Stream compressedStream) =>
CompressStreamAsync(originalStream, compressedStream).GetAwaiter().GetResult();
return compressedFileName;
}

public static async Task CompressStreamAsync(
Stream originalStream,
Stream compressedStream,
CancellationToken cancel = default
)
public static void CompressStream(Stream originalStream, Stream compressedStream)
{
using GZipStream? compressor = new(compressedStream, GetCompressionLevel());
await originalStream.CopyToAsync(compressor, cancel);
originalStream.CopyTo(compressor);
}

public static byte[] DecompressBytes(byte[] bytes) =>
DecompressBytesAsync(bytes).GetAwaiter().GetResult();

public static async Task<byte[]> DecompressBytesAsync(
byte[] bytes,
CancellationToken cancel = default
)
public static byte[] DecompressBytes(byte[] bytes)
{
using MemoryStream? inputStream = new(bytes);
using MemoryStream? outputStream = new();
using (GZipStream? compressionStream = new(inputStream, CompressionMode.Decompress))
{
await compressionStream.CopyToAsync(outputStream, cancel);
}
compressionStream.CopyTo(outputStream);

return outputStream.ToArray();
}

public static void DecompressFile(string compressedFileName, string outputFileName) =>
DecompressFileAsync(compressedFileName, outputFileName).GetAwaiter().GetResult();

public static async Task DecompressFileAsync(
string compressedFileName,
string outputFileName,
CancellationToken cancel = default
)
public static string DecompressFile(string compressedFileName, string outputFileName)
{
using FileStream compressedFileStream = File.Open(compressedFileName, FileMode.Open);
using FileStream outputFileStream = File.Create(outputFileName);
await DecompressStreamAsync(compressedFileStream, outputFileStream, cancel);
}
DecompressStream(compressedFileStream, outputFileStream);

public static void DecompressStream(Stream compressedStream, Stream outputStream) =>
DecompressStreamAsync(compressedStream, outputStream).GetAwaiter().GetResult();
return outputFileName;
}

public static async Task DecompressStreamAsync(
Stream compressedStream,
Stream outputStream,
CancellationToken cancel = default
)
public static void DecompressStream(Stream compressedStream, Stream outputStream)
{
using GZipStream? decompressor = new(compressedStream, CompressionMode.Decompress);
await decompressor.CopyToAsync(outputStream, cancel);
decompressor.CopyTo(outputStream);
}
}
}
Expand Down
81 changes: 56 additions & 25 deletions Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,11 @@ static void Main(string[] args)
string? execDirectory = Path.GetDirectoryName(execPath);

string? dataFile;
string? dataDirectory; // game data directory
string? dataDirectory; // Can be "Game_Data" or "Build" directory

string? webDataFile = null; // WebGL.[data, data.br, data.gz]
string[] webDataFileExtensions = { ".data", ".data.br", ".data.gz" };
string? unpackedWebDataDirectory = null;
string? compressionType = null;
FileStream? bundleStream = null;

Expand Down Expand Up @@ -113,6 +114,7 @@ static void Main(string[] args)
temporaryFiles.Add(decompressedWebData);
loadType = LoadTypes.WebData;

// Decompress WebGL.data.* first
switch (compressionType)
{
case ".data.br":
Expand All @@ -124,7 +126,10 @@ static void Main(string[] args)
}

// Unpack WebGL.data and set the dataDirectory to output folder
dataDirectory = UnityWebDataHelper.UnpackBundleToFile(decompressedWebData);
unpackedWebDataDirectory = UnityWebDataHelper.UnpackWebDataToFile(
decompressedWebData
);
dataDirectory = unpackedWebDataDirectory;

break;
default:
Expand Down Expand Up @@ -276,30 +281,27 @@ static void Main(string[] args)
logoPointer
);

switch (loadType)
if (logoExtInfo.baseField != null)
{
case LoadTypes.Asset:
// Get the base field
AssetTypeValueField? logoBase = logoExtInfo.baseField;
string? logoName = logoBase["m_Name"].AsString;
// Get the base field
AssetTypeValueField? logoBase = logoExtInfo.baseField;
string? logoName = logoBase["m_Name"].AsString;

// If it's Unity splash screen logo
if (logoName.Contains("UnitySplash-cube"))
unityLogo = data;

break;
case LoadTypes.Bundle:
/*
* IDK why AssetsTools won't load "UnitySplash-cube"
* external asset while in Bundle file. So, we can
* check it's name and remove it like before.
*
* Alternatively, we can still find it by checking
* the base field. If it's null, then it is.
*/
if (logoExtInfo.baseField == null)
unityLogo = data;
break;
// If it's Unity splash screen logo
if (logoName.Contains("UnitySplash-cube"))
unityLogo = data;
}
else
{
/*
* IDK why AssetsTools won't load "UnitySplash-cube"
* external asset while in Bundle file. So, we can
* check it's name and remove it like before.
*
* Alternatively, we can still find it by checking
* the base field. If it's null, then it is.
*/
unityLogo = data;
}
}

Expand Down Expand Up @@ -368,7 +370,6 @@ static void Main(string[] args)
AssetBundleFile? uncompressedBundle = new();
uncompressedBundle.Read(new AssetsFileReader(uncompressedBundleStream));

// using AssetsFileReader reader = new(uncompressedBundleStream);
using AssetsFileWriter writer = new(dataFile);
uncompressedBundle.Pack(
uncompressedBundle.Reader,
Expand Down Expand Up @@ -396,6 +397,36 @@ static void Main(string[] args)
assetsManager.UnloadAllAssetsFiles(true);
Utility.CleanUp(temporaryFiles);

if (!loadType.Equals(LoadTypes.WebData))
{
Console.WriteLine("Packing WebGL...");

string? webGLdataPath = Path.Combine(execDirectory, "Build", "WebGL.data");

UnityWebDataHelper.PackFilesToWebData(
unpackedWebDataDirectory,
webGLdataPath
);

// Delete WebGL folder
Directory.Delete(unpackedWebDataDirectory, true);

// Compress WebGL.data if using compression
Console.WriteLine("Compressing WebGL.data");
switch (compressionType)
{
case ".data.br":
BrotliUtils.CompressFile(webGLdataPath, $"{webGLdataPath}.br");
break;
case ".data.gz":
GZipUtils.CompressFile(webGLdataPath, $"{webGLdataPath}.gz");
break;
}

// Delete WebGL.data
File.Delete(webGLdataPath);
}

Console.WriteLine("Successfully removed Unity splash screen. Enjoy :) \n");
Console.WriteLine(
"Don't forget to visit USSR repo: https://github.com/kiraio-moe/USSR and give it a star!"
Expand Down
Loading

0 comments on commit 42cf178

Please sign in to comment.