diff --git a/perf/War3Net.Drawing.Blp.Benchmarks/War3Net.Drawing.Blp.Benchmarks.csproj b/perf/War3Net.Drawing.Blp.Benchmarks/War3Net.Drawing.Blp.Benchmarks.csproj index 9452fa72..7b616b09 100644 --- a/perf/War3Net.Drawing.Blp.Benchmarks/War3Net.Drawing.Blp.Benchmarks.csproj +++ b/perf/War3Net.Drawing.Blp.Benchmarks/War3Net.Drawing.Blp.Benchmarks.csproj @@ -6,7 +6,11 @@ Exe - + + + + + diff --git a/src/War3Net.Build.Core/Environment/MapEnvironmentFormatVersion.cs b/src/War3Net.Build.Core/Environment/MapEnvironmentFormatVersion.cs index 843e538d..b858060d 100644 --- a/src/War3Net.Build.Core/Environment/MapEnvironmentFormatVersion.cs +++ b/src/War3Net.Build.Core/Environment/MapEnvironmentFormatVersion.cs @@ -17,5 +17,8 @@ public enum MapEnvironmentFormatVersion { /// The initial version. v11 = 11, + + /// Introduced in patch 2.0.3. + v12 = 12, } } \ No newline at end of file diff --git a/src/War3Net.Build.Core/Environment/TerrainTile.cs b/src/War3Net.Build.Core/Environment/TerrainTile.cs index 02122c71..5fa642d2 100644 --- a/src/War3Net.Build.Core/Environment/TerrainTile.cs +++ b/src/War3Net.Build.Core/Environment/TerrainTile.cs @@ -21,7 +21,8 @@ public sealed partial class TerrainTile private ushort _heightData; private ushort _waterDataAndEdgeFlag; - private byte _textureDataAndFlags; + private byte _textureData; + private TileFlags _tileFlags; private byte _variationData; private byte _cliffData; @@ -52,32 +53,38 @@ public bool IsEdgeTile public int Texture { - get => _textureDataAndFlags & 0x0F; - set => _textureDataAndFlags = (value >= 0 && value <= 0x0F) ? (byte)(value | (_textureDataAndFlags & 0xF0)) : throw new ArgumentOutOfRangeException(nameof(value)); + get => _textureData; + set => _textureData = (value >= 0 && value < 64) ? (byte)value : throw new ArgumentOutOfRangeException(nameof(value)); + } + + public TileFlags Flags + { + get => _tileFlags; + set => _tileFlags = value; } public bool IsRamp { - get => (_textureDataAndFlags & 0x10) != 0; - set => _textureDataAndFlags = (byte)(value ? _textureDataAndFlags | 0x10 : _textureDataAndFlags & 0xEF); + get => _tileFlags.HasFlag(TileFlags.Ramp); + set => _tileFlags = value ? _tileFlags | TileFlags.Ramp : _tileFlags & ~TileFlags.Ramp; } public bool IsBlighted { - get => (_textureDataAndFlags & 0x20) != 0; - set => _textureDataAndFlags = (byte)(value ? _textureDataAndFlags | 0x20 : _textureDataAndFlags & 0xDF); + get => _tileFlags.HasFlag(TileFlags.Blighted); + set => _tileFlags = value ? _tileFlags | TileFlags.Blighted : _tileFlags & ~TileFlags.Blighted; } public bool IsWater { - get => (_textureDataAndFlags & 0x40) != 0; - set => _textureDataAndFlags = (byte)(value ? _textureDataAndFlags | 0x40 : _textureDataAndFlags & 0xBF); + get => _tileFlags.HasFlag(TileFlags.Water); + set => _tileFlags = value ? _tileFlags | TileFlags.Water : _tileFlags & ~TileFlags.Water; } public bool IsBoundary { - get => (_textureDataAndFlags & 0x80) != 0; - set => _textureDataAndFlags = (byte)(value ? _textureDataAndFlags | 0x80 : _textureDataAndFlags & 0x7F); + get => _tileFlags.HasFlag(TileFlags.Boundary); + set => _tileFlags = value ? _tileFlags | TileFlags.Boundary : _tileFlags & ~TileFlags.Boundary; } public int Variation diff --git a/src/War3Net.Build.Core/Environment/TileFlags.cs b/src/War3Net.Build.Core/Environment/TileFlags.cs new file mode 100644 index 00000000..8c446541 --- /dev/null +++ b/src/War3Net.Build.Core/Environment/TileFlags.cs @@ -0,0 +1,20 @@ +// ------------------------------------------------------------------------------ +// +// Licensed under the MIT license. +// See the LICENSE file in the project root for more information. +// +// ------------------------------------------------------------------------------ + +using System; + +namespace War3Net.Build.Environment +{ + [Flags] + public enum TileFlags : byte + { + Ramp = 1 << 0, + Blighted = 1 << 1, + Water = 1 << 2, + Boundary = 1 << 3, + } +} \ No newline at end of file diff --git a/src/War3Net.Build.Core/Resources/GameBuilds.json b/src/War3Net.Build.Core/Resources/GameBuilds.json index bc220435..01e8bc15 100644 --- a/src/War3Net.Build.Core/Resources/GameBuilds.json +++ b/src/War3Net.Build.Core/Resources/GameBuilds.json @@ -102,5 +102,6 @@ { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2024-12-17", "GamePatch": "v2_0_1", "Version": "2.0.1.22474", "EditorVersion": 6115 }, { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2025-04-15", "GamePatch": "v2_0_2", "Version": "2.0.2.22761", "EditorVersion": 6115 }, { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2025-07-17", "GamePatch": "v2_0_3", "Version": "2.0.3.22978", "EditorVersion": 6116 }, - { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2025-07-22", "GamePatch": "v2_0_3", "Version": "2.0.3.22988", "EditorVersion": 6116 } + { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2025-07-22", "GamePatch": "v2_0_3", "Version": "2.0.3.22988", "EditorVersion": 6116 }, + { "GameExpansion": 3, "GameReleaseType": "Retail", "ReleaseDate": "2025-09-15", "GamePatch": "v2_0_3", "Version": "2.0.3.23101", "EditorVersion": 6116 } ] \ No newline at end of file diff --git a/src/War3Net.Build.Core/Serialization/Binary/Environment/TerrainTile.cs b/src/War3Net.Build.Core/Serialization/Binary/Environment/TerrainTile.cs index 1947242f..8415da06 100644 --- a/src/War3Net.Build.Core/Serialization/Binary/Environment/TerrainTile.cs +++ b/src/War3Net.Build.Core/Serialization/Binary/Environment/TerrainTile.cs @@ -20,7 +20,23 @@ internal void ReadFrom(BinaryReader reader, MapEnvironmentFormatVersion formatVe { _heightData = reader.ReadUInt16(); _waterDataAndEdgeFlag = reader.ReadUInt16(); - _textureDataAndFlags = reader.ReadByte(); + + if (formatVersion >= MapEnvironmentFormatVersion.v12) + { + var textureDataAndFlags = reader.ReadByte(); + var remainingFlags = reader.ReadByte(); + + _textureData = (byte)(textureDataAndFlags & 0x3F); + _tileFlags = (TileFlags)(((textureDataAndFlags & 0xC0) >> 6) | ((remainingFlags & 0x03) << 2)); + } + else + { + var textureDataAndFlags = reader.ReadByte(); + + _textureData = (byte)(textureDataAndFlags & 0x0F); + _tileFlags = (TileFlags)((textureDataAndFlags & 0xF0) >> 4); + } + _variationData = reader.ReadByte(); _cliffData = reader.ReadByte(); } @@ -29,7 +45,17 @@ internal void WriteTo(BinaryWriter writer, MapEnvironmentFormatVersion formatVer { writer.Write(_heightData); writer.Write(_waterDataAndEdgeFlag); - writer.Write(_textureDataAndFlags); + + if (formatVersion >= MapEnvironmentFormatVersion.v12) + { + writer.Write((byte)((_textureData & 0x3F) | (((byte)_tileFlags & 0x03) << 6))); + writer.Write((byte)(((byte)_tileFlags & 0x0C) >> 2)); + } + else + { + writer.Write((byte)((_textureData & 0x0F) | (((byte)_tileFlags & 0x0F) << 4))); + } + writer.Write(_variationData); writer.Write(_cliffData); } diff --git a/tests/War3Net.TestTools.UnitTesting/TestData/Environment/v12.w3e b/tests/War3Net.TestTools.UnitTesting/TestData/Environment/v12.w3e new file mode 100644 index 00000000..f1a17a85 Binary files /dev/null and b/tests/War3Net.TestTools.UnitTesting/TestData/Environment/v12.w3e differ