From 4e735ad8f34b0d5ca3ec436d62eadde23c4b7cab Mon Sep 17 00:00:00 2001 From: 7H3LaughingMan <7H3LaughingMan@proton.me> Date: Tue, 29 Apr 2025 14:24:13 -0500 Subject: [PATCH 1/3] Add ZstdSharp Reference --- src/DotTiled/DotTiled.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/DotTiled/DotTiled.csproj b/src/DotTiled/DotTiled.csproj index d8d83a5..837264e 100644 --- a/src/DotTiled/DotTiled.csproj +++ b/src/DotTiled/DotTiled.csproj @@ -26,4 +26,8 @@ + + + + From 2388af6b523402984e08e0ae050953108ee7c526 Mon Sep 17 00:00:00 2001 From: 7H3LaughingMan <7H3LaughingMan@proton.me> Date: Tue, 29 Apr 2025 14:24:45 -0500 Subject: [PATCH 2/3] ZStd Support --- src/DotTiled/Serialization/Helpers.cs | 6 ++++++ src/DotTiled/Serialization/Tmj/TmjReaderBase.Data.cs | 2 +- src/DotTiled/Serialization/Tmj/TmjReaderBase.TileLayer.cs | 1 + src/DotTiled/Serialization/Tmx/TmxReaderBase.Data.cs | 2 +- 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/DotTiled/Serialization/Helpers.cs b/src/DotTiled/Serialization/Helpers.cs index 28d6aec..0e7e51c 100644 --- a/src/DotTiled/Serialization/Helpers.cs +++ b/src/DotTiled/Serialization/Helpers.cs @@ -46,6 +46,12 @@ internal static partial class Helpers return ReadMemoryStreamAsInt32Array(decompressedStream); } + internal static uint[] DecompressZStd(MemoryStream stream) + { + using var decompressedStream = new ZstdSharp.DecompressionStream(stream); + return ReadMemoryStreamAsInt32Array(decompressedStream); + } + internal static uint[] ReadBytesAsInt32Array(byte[] bytes) { var intArray = new uint[bytes.Length / 4]; diff --git a/src/DotTiled/Serialization/Tmj/TmjReaderBase.Data.cs b/src/DotTiled/Serialization/Tmj/TmjReaderBase.Data.cs index 904321b..9d1e5db 100644 --- a/src/DotTiled/Serialization/Tmj/TmjReaderBase.Data.cs +++ b/src/DotTiled/Serialization/Tmj/TmjReaderBase.Data.cs @@ -61,7 +61,7 @@ public abstract partial class TmjReaderBase { DataCompression.GZip => Helpers.DecompressGZip(stream), DataCompression.ZLib => Helpers.DecompressZLib(stream), - DataCompression.ZStd => throw new NotSupportedException("ZStd compression is not supported."), + DataCompression.ZStd => Helpers.DecompressZStd(stream), _ => throw new InvalidOperationException($"Unsupported compression '{compression}'.") }; diff --git a/src/DotTiled/Serialization/Tmj/TmjReaderBase.TileLayer.cs b/src/DotTiled/Serialization/Tmj/TmjReaderBase.TileLayer.cs index 862df4d..22d65b6 100644 --- a/src/DotTiled/Serialization/Tmj/TmjReaderBase.TileLayer.cs +++ b/src/DotTiled/Serialization/Tmj/TmjReaderBase.TileLayer.cs @@ -16,6 +16,7 @@ public abstract partial class TmjReaderBase { "zlib" => DataCompression.ZLib, "gzip" => DataCompression.GZip, + "zstd" => DataCompression.ZStd, "" => Optional.Empty, _ => throw new JsonException($"Unsupported compression '{s}'.") }); diff --git a/src/DotTiled/Serialization/Tmx/TmxReaderBase.Data.cs b/src/DotTiled/Serialization/Tmx/TmxReaderBase.Data.cs index e60f641..a01a582 100644 --- a/src/DotTiled/Serialization/Tmx/TmxReaderBase.Data.cs +++ b/src/DotTiled/Serialization/Tmx/TmxReaderBase.Data.cs @@ -77,7 +77,7 @@ public abstract partial class TmxReaderBase { DataCompression.GZip => Helpers.DecompressGZip(bytes), DataCompression.ZLib => Helpers.DecompressZLib(bytes), - DataCompression.ZStd => throw new NotSupportedException("ZStd compression is not supported."), + DataCompression.ZStd => Helpers.DecompressZStd(bytes), _ => throw new XmlException("Invalid compression") }; From 9c446239d73584dca067b8e5228f43656458ad02 Mon Sep 17 00:00:00 2001 From: 7H3LaughingMan <7H3LaughingMan@proton.me> Date: Tue, 29 Apr 2025 14:24:58 -0500 Subject: [PATCH 3/3] ZStd Testing --- .../default-map-base64-zstd.cs | 52 +++++++++++++++++++ .../default-map-base64-zstd.tmj | 30 +++++++++++ .../default-map-base64-zstd.tmx | 8 +++ .../UnitTests/Serialization/TestData.cs | 1 + 4 files changed, 91 insertions(+) create mode 100644 src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.cs create mode 100644 src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmj create mode 100644 src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmx diff --git a/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.cs b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.cs new file mode 100644 index 0000000..5aa5401 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.cs @@ -0,0 +1,52 @@ +namespace DotTiled.Tests; + +public partial class TestData +{ + public static Map DefaultMapBase64ZStd() => new Map + { + Class = "", + Orientation = MapOrientation.Orthogonal, + Width = 5, + Height = 5, + TileWidth = 32, + TileHeight = 32, + Infinite = false, + ParallaxOriginX = 0, + ParallaxOriginY = 0, + RenderOrder = RenderOrder.RightDown, + CompressionLevel = -1, + BackgroundColor = new TiledColor { R = 0, G = 0, B = 0, A = 0 }, + Version = "1.10", + TiledVersion = "1.11.2", + NextLayerID = 2, + NextObjectID = 1, + Layers = [ + new TileLayer + { + ID = 1, + Name = "Tile Layer 1", + Width = 5, + Height = 5, + Data = new Data + { + Encoding = DataEncoding.Base64, + Compression = DataCompression.ZStd, + GlobalTileIDs = new Optional([ + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + ]), + FlippingFlags = new Optional([ + FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, + FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, + FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, + FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, + FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None, FlippingFlags.None + ]) + } + } + ] + }; +} diff --git a/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmj b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmj new file mode 100644 index 0000000..49e6a43 --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmj @@ -0,0 +1,30 @@ +{ "compressionlevel":-1, + "height":5, + "infinite":false, + "layers":[ + { + "compression":"zstd", + "data":"KLUv\/SBkRQAACAABAIDUCQE=", + "encoding":"base64", + "height":5, + "id":1, + "name":"Tile Layer 1", + "opacity":1, + "type":"tilelayer", + "visible":true, + "width":5, + "x":0, + "y":0 + }], + "nextlayerid":2, + "nextobjectid":1, + "orientation":"orthogonal", + "renderorder":"right-down", + "tiledversion":"1.11.2", + "tileheight":32, + "tilesets":[], + "tilewidth":32, + "type":"map", + "version":"1.10", + "width":5 +} \ No newline at end of file diff --git a/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmx b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmx new file mode 100644 index 0000000..a8a069a --- /dev/null +++ b/src/DotTiled.Tests/TestData/Maps/default-map-base64-zstd/default-map-base64-zstd.tmx @@ -0,0 +1,8 @@ + + + + + KLUv/SBkRQAACAABAIDUCQE= + + + diff --git a/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs b/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs index 2256f83..55e5291 100644 --- a/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs +++ b/src/DotTiled.Tests/UnitTests/Serialization/TestData.cs @@ -37,6 +37,7 @@ public static partial class TestData [GetMapPath("default-map-base64"), (string f) => DefaultMapBase64(), Array.Empty()], [GetMapPath("default-map-base64-gzip"), (string f) => DefaultMapBase64GZip(), Array.Empty()], [GetMapPath("default-map-base64-zlib"), (string f) => DefaultMapBase64ZLib(), Array.Empty()], + [GetMapPath("default-map-base64-zstd"), (string f) => DefaultMapBase64ZStd(), Array.Empty()], [GetMapPath("map-duplicate-object-id-bug"), (string f) => MapDuplicateObjectIdBug(f), Array.Empty()], [GetMapPath("map-with-common-props"), (string f) => MapWithCommonProps(), Array.Empty()], [GetMapPath("map-with-custom-type-props"), (string f) => MapWithCustomTypeProps(), MapWithCustomTypePropsCustomTypeDefinitions()],