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