diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index af46380a8..16a411160 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -14,10 +14,10 @@ jobs: fail-fast: false matrix: include: - - os: macos-12 - name: MacOS 12 - os: macos-13 name: MacOS 13 + - os: macos-14 + name: MacOS 14 steps: - uses: actions/checkout@v4 @@ -27,6 +27,12 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: 8.0.x + - name: Install Prerequisites + run: | + brew update + brew install icu4c libdeflate zstd argon2 + - name: Set Library Path + run: echo "DYLD_LIBRARY_PATH=/opt/homebrew/lib:\$DYLD_LIBRARY_PATH" >> $GITHUB_ENV - name: Build run: ./publish.cmd Release - name: Migration Changes @@ -75,10 +81,10 @@ jobs: run: dnf upgrade --refresh -y && dnf install -y epel-release epel-next-release if: ${{ startsWith(matrix.name, 'CentOS') }} - name: Install Prerequisites using dnf - run: dnf makecache --refresh && dnf install -y findutils libicu zlib-devel zstd libargon2-devel tzdata + run: dnf makecache --refresh && dnf install -y findutils libicu libdeflate-devel zstd libargon2-devel if: ${{ matrix.packageManager == 'dnf' }} - name: Install Prerequisites using apt - run: apt-get update -y && apt-get install -y curl libicu-dev libz-dev zstd libargon2-dev tzdata + run: apt-get update -y && apt-get install -y curl libicu-dev libdeflate-dev zstd libargon2-dev if: ${{ matrix.packageManager == 'apt' }} - uses: actions/checkout@v4 with: diff --git a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPackets.cs b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPackets.cs index 17f29ca34..d0b8aa069 100644 --- a/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPackets.cs +++ b/Projects/Server.Tests/Tests/Network/Packets/Outgoing/GumpPackets.cs @@ -3,6 +3,7 @@ using System.Buffers; using System.Collections.Generic; using System.IO.Compression; using System.Text; +using Server.Compression; using Server.Gumps; using Server.Network; @@ -165,14 +166,11 @@ namespace Server.Tests wantLength &= ~4095; var packBuffer = ArrayPool.Shared.Rent(wantLength); + var bytesPacked = Deflate.Standard.Pack(packBuffer, buffer.AsSpan(0, length)); - var packLength = wantLength; - - Zlib.Pack(packBuffer, ref packLength, buffer, length, ZlibQuality.Default); - - Stream.Write(4 + packLength); + Stream.Write(4 + bytesPacked); Stream.Write(length); - Stream.Write(packBuffer, 0, packLength); + Stream.Write(packBuffer, 0, bytesPacked); ArrayPool.Shared.Return(packBuffer); } diff --git a/Projects/Server/Compression/Deflate.cs b/Projects/Server/Compression/Deflate.cs new file mode 100644 index 000000000..0442794c4 --- /dev/null +++ b/Projects/Server/Compression/Deflate.cs @@ -0,0 +1,23 @@ +/************************************************************************* + * ModernUO * + * Copyright 2019-2024 - ModernUO Development Team * + * Email: hi@modernuo.com * + * File: Deflate.cs * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + *************************************************************************/ + +using System.IO.Compression; + +namespace Server.Compression; + +public static class Deflate +{ + public static LibDeflateBinding Standard { get; } = new(); +} diff --git a/Projects/Server/MultiData.cs b/Projects/Server/MultiData.cs index e1f456722..f5860c3f3 100644 --- a/Projects/Server/MultiData.cs +++ b/Projects/Server/MultiData.cs @@ -19,6 +19,7 @@ using System.Collections.Generic; using System.IO; using System.IO.Compression; using Server.Buffers; +using Server.Compression; namespace Server; @@ -72,8 +73,8 @@ public static class MultiData } var decompressedSize = entry.Size; - if (Zlib.Unpack(compressionBuffer, ref decompressedSize, buffer, entry.CompressedSize) != ZlibError.Okay - || decompressedSize != entry.Size) + if (Deflate.Standard.Unpack(compressionBuffer, buffer, out var bytesDecompressed) != LibDeflateResult.Success + || decompressedSize != bytesDecompressed) { throw new FileLoadException($"Error loading file {stream.Name}. Failed to unpack entry {i}."); } @@ -118,11 +119,7 @@ public static class MultiData } STArrayPool.Shared.Return(buffer); - - if (compressionBuffer != null) - { - STArrayPool.Shared.Return(compressionBuffer); - } + STArrayPool.Shared.Return(compressionBuffer); } private static void LoadMul(bool postHSMulFormat) diff --git a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs b/Projects/Server/Network/Packets/OutgoingGumpPackets.cs index 8fe6fc066..cc89cc94d 100644 --- a/Projects/Server/Network/Packets/OutgoingGumpPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingGumpPackets.cs @@ -16,10 +16,9 @@ using System; using System.Buffers; using System.IO; -using System.IO.Compression; using System.Runtime.CompilerServices; -using Server.Buffers; using Server.Collections; +using Server.Compression; using Server.Gumps; using Server.Logging; @@ -49,7 +48,6 @@ public static class OutgoingGumpPackets private static readonly byte[] _layoutBuffer = GC.AllocateUninitializedArray(0x20000); private static readonly byte[] _stringsBuffer = GC.AllocateUninitializedArray(0x20000); - private static readonly byte[] _packBuffer = GC.AllocateUninitializedArray(0x20000); private static readonly OrderedSet _stringsList = new(); [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -63,36 +61,21 @@ public static class OutgoingGumpPackets return; } - var wantLength = Zlib.MaxPackSize(length); - var packBuffer = _packBuffer; - byte[] rentedBuffer = null; + var dest = writer.RawBuffer[(writer.Position + 8)..]; - if (wantLength > packBuffer.Length) + var bytesPacked = Deflate.Standard.Pack(dest, span); + if (bytesPacked == 0) { - packBuffer = rentedBuffer = STArrayPool.Shared.Rent(wantLength); - } - - var packLength = wantLength; - - var error = Zlib.Pack(packBuffer, ref packLength, span, length, ZlibQuality.Default); - - if (error != ZlibError.Okay) - { - logger.Warning("Gump compression failed: {Error}", error); + logger.Warning("Gump compression failed"); writer.Write(4); writer.Write(0); return; } - writer.Write(4 + packLength); + writer.Write(4 + bytesPacked); writer.Write(length); - writer.Write(packBuffer.AsSpan(0, packLength)); - - if (rentedBuffer != null) - { - STArrayPool.Shared.Return(rentedBuffer); - } + writer.Seek(bytesPacked, SeekOrigin.Current); } public static void SendDisplayGump(this NetState ns, Gump gump, out int switches, out int entries) @@ -141,11 +124,8 @@ public static class OutgoingGumpPackets stringsWriter.WriteBigUni(s); } - var worstLayoutLength = Zlib.MaxPackSize(layoutWriter.BytesWritten); - var worstStringsLength = Zlib.MaxPackSize(stringsWriter.BytesWritten); - var maxLength = 40 + worstLayoutLength + worstStringsLength; - var writer = new SpanWriter(maxLength); + var writer = new SpanWriter(0x10000); writer.Write((byte)0xDD); // Packet ID writer.Seek(2, SeekOrigin.Current); @@ -171,6 +151,8 @@ public static class OutgoingGumpPackets { _stringsList.Clear(); } + + writer.Dispose(); } public static void SendDisplaySignGump(this NetState ns, Serial serial, int gumpId, string unknown, string caption) diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index 073b6d7a9..acac1aea1 100755 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -29,13 +29,15 @@ - + + + + - diff --git a/Projects/UOContent.Tests/Tests/Multis/Houses/HousePackets.cs b/Projects/UOContent.Tests/Tests/Multis/Houses/HousePackets.cs index 3b3f91be0..109e53b7a 100644 --- a/Projects/UOContent.Tests/Tests/Multis/Houses/HousePackets.cs +++ b/Projects/UOContent.Tests/Tests/Multis/Houses/HousePackets.cs @@ -2,6 +2,7 @@ using System; using System.Buffers; using System.IO; using System.IO.Compression; +using Server.Compression; namespace Server.Network { @@ -209,20 +210,14 @@ namespace Server.Network var inflatedBuffer = planeBuffers[i]; - var deflatedLength = deflatedBuffer.Length; - var ce = Zlib.Pack( + var deflatedLength = Deflate.Standard.Pack( deflatedBuffer, - ref deflatedLength, - inflatedBuffer, - size, - ZlibQuality.Default + inflatedBuffer.AsSpan(0, size) ); - if (ce != ZlibError.Okay) + if (deflatedLength == 0) { - Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); - deflatedLength = 0; - size = 0; + Console.WriteLine("Compression error"); } Write((byte)(0x20 | i)); @@ -247,20 +242,14 @@ namespace Server.Network var inflatedBuffer = stairBuffers[i]; - var deflatedLength = deflatedBuffer.Length; - var ce = Zlib.Pack( + var deflatedLength = Deflate.Standard.Pack( deflatedBuffer, - ref deflatedLength, - inflatedBuffer, - size, - ZlibQuality.Default + inflatedBuffer.AsSpan(0, size) ); - if (ce != ZlibError.Okay) + if (deflatedLength == 0) { - Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce); - deflatedLength = 0; - size = 0; + Console.WriteLine("Compression error"); } Write((byte)(9 + i)); diff --git a/Projects/UOContent/Multis/Houses/HousePackets.cs b/Projects/UOContent/Multis/Houses/HousePackets.cs index 25dae3088..7f8308c0d 100644 --- a/Projects/UOContent/Multis/Houses/HousePackets.cs +++ b/Projects/UOContent/Multis/Houses/HousePackets.cs @@ -16,252 +16,245 @@ using System; using System.Buffers; using System.IO; -using System.IO.Compression; using System.Runtime.CompilerServices; +using Server.Compression; using Server.Logging; using Server.Network; -namespace Server.Multis +namespace Server.Multis; + +public static class HousePackets { - public static class HousePackets + private static readonly ILogger logger = LogFactory.GetLogger(typeof(HousePackets)); + + public static void SendBeginHouseCustomization(this NetState ns, Serial house) { - private static readonly ILogger logger = LogFactory.GetLogger(typeof(HousePackets)); - - public static void SendBeginHouseCustomization(this NetState ns, Serial house) + if (ns.CannotSendPackets()) { - if (ns.CannotSendPackets()) - { - return; - } - - var writer = new SpanWriter(stackalloc byte[17]); - writer.Write((byte)0xBF); // Packet Id - writer.Write((ushort)17); - writer.Write((short)0x20); // Sub-packet - writer.Write(house); - writer.Write((byte)0x04); // command - writer.Write((ushort)0x0000); - writer.Write((ushort)0xFFFF); - writer.Write((ushort)0xFFFF); - writer.Write((byte)0xFF); - - ns.Send(writer.Span); + return; } - public static void SendEndHouseCustomization(this NetState ns, Serial house) + var writer = new SpanWriter(stackalloc byte[17]); + writer.Write((byte)0xBF); // Packet Id + writer.Write((ushort)17); + writer.Write((short)0x20); // Sub-packet + writer.Write(house); + writer.Write((byte)0x04); // command + writer.Write((ushort)0x0000); + writer.Write((ushort)0xFFFF); + writer.Write((ushort)0xFFFF); + writer.Write((byte)0xFF); + + ns.Send(writer.Span); + } + + public static void SendEndHouseCustomization(this NetState ns, Serial house) + { + if (ns.CannotSendPackets()) { - if (ns.CannotSendPackets()) - { - return; - } - - var writer = new SpanWriter(stackalloc byte[17]); - writer.Write((byte)0xBF); // Packet Id - writer.Write((ushort)17); - writer.Write((short)0x20); // Sub-packet - writer.Write(house); - writer.Write((byte)0x05); // command - writer.Write((ushort)0x0000); - writer.Write((ushort)0xFFFF); - writer.Write((ushort)0xFFFF); - writer.Write((byte)0xFF); - - ns.Send(writer.Span); + return; } - public static void SendDesignStateGeneral(this NetState ns, Serial house, int revision) + var writer = new SpanWriter(stackalloc byte[17]); + writer.Write((byte)0xBF); // Packet Id + writer.Write((ushort)17); + writer.Write((short)0x20); // Sub-packet + writer.Write(house); + writer.Write((byte)0x05); // command + writer.Write((ushort)0x0000); + writer.Write((ushort)0xFFFF); + writer.Write((ushort)0xFFFF); + writer.Write((byte)0xFF); + + ns.Send(writer.Span); + } + + public static void SendDesignStateGeneral(this NetState ns, Serial house, int revision) + { + if (ns.CannotSendPackets()) { - if (ns.CannotSendPackets()) - { - return; - } - - var writer = new SpanWriter(stackalloc byte[13]); - writer.Write((byte)0xBF); // Packet Id - writer.Write((ushort)13); - writer.Write((short)0x1D); // Sub-packet - writer.Write(house); - writer.Write(revision); - - ns.Send(writer.Span); + return; } - private const int planeCount = 9; - private const int maxPlaneLength = 0x400; - private const int maxPerPlaneOffsetBuffer = 750; - private static readonly int maxPackedPlaneOffsetBuffer = Zlib.MaxPackSize(maxPerPlaneOffsetBuffer * 5); + var writer = new SpanWriter(stackalloc byte[13]); + writer.Write((byte)0xBF); // Packet Id + writer.Write((ushort)13); + writer.Write((short)0x1D); // Sub-packet + writer.Write(house); + writer.Write(revision); - public static byte[] CreateHouseDesignStateDetailed(Serial serial, int revision, MultiComponentList components) + ns.Send(writer.Span); + } + + private const int planeCount = 9; + private const int maxPlaneLength = 0x400; + private const int maxPerPlaneOffsetBuffer = 750; + + public static byte[] CreateHouseDesignStateDetailed(Serial serial, int revision, MultiComponentList components) + { + var xMin = components.Min.X; + var yMin = components.Min.Y; + var xMax = components.Max.X; + var yMax = components.Max.Y; + var width = xMax - xMin + 1; + var height = yMax - yMin + 1; + var tiles = components.List; + + var planeLength = width * height * 2; + using var planeOffsetWriter = new SpanWriter(0x500, true); + using var planesWriter = new SpanWriter(planeLength * planeCount); + + Span planesUsed = stackalloc bool[9]; + planesUsed.Clear(); + + int index; + var totalPlaneOffsets = 0; + var totalPlanes = 0; + + for (var i = 0; i < tiles.Length; ++i) { - var xMin = components.Min.X; - var yMin = components.Min.Y; - var xMax = components.Max.X; - var yMax = components.Max.Y; - var width = xMax - xMin + 1; - var height = yMax - yMin + 1; - var tiles = components.List; + var mte = tiles[i]; + var x = mte.OffsetX - xMin; + var y = mte.OffsetY - yMin; + int z = mte.OffsetZ; + var floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0; - var planeLength = width * height * 2; - using var planeOffsetWriter = new SpanWriter(0x500, true); - using var planesWriter = new SpanWriter(planeLength * planeCount); - - Span planesUsed = stackalloc bool[9]; - planesUsed.Clear(); - - int index; - var totalPlaneOffsets = 0; - var totalPlanes = 0; - - for (var i = 0; i < tiles.Length; ++i) + int plane = z switch { - var mte = tiles[i]; - var x = mte.OffsetX - xMin; - var y = mte.OffsetY - yMin; - int z = mte.OffsetZ; - var floor = TileData.ItemTable[mte.ItemId & TileData.MaxItemValue].Height <= 0; + 0 => 0, + 7 => 1, + 27 => 2, + 47 => 3, + 67 => 4, + _ => -1 + }; - int plane = z switch + if (plane > -1) + { + int size; + if (plane == 0) { - 0 => 0, - 7 => 1, - 27 => 2, - 47 => 3, - 67 => 4, - _ => -1 - }; - - if (plane > -1) + size = height; + } + else if (floor) { - int size; - if (plane == 0) - { - size = height; - } - else if (floor) - { - size = height - 2; - x -= 1; - y -= 1; - } - else - { - size = height - 1; - plane += 4; - } - - index = (x * size + y) * 2; - - if (x >= 0 && y >= 0 && y < size && index + 1 < maxPlaneLength) - { - var planeUsed = planesUsed[plane]; - var planeWriterIndex = planeLength * plane; - if (!planeUsed) - { - planesUsed[plane] = true; - totalPlanes++; - planesWriter.Seek(planeWriterIndex, SeekOrigin.Begin); - planesWriter.Clear(planeLength); - } - - planesWriter.Seek(planeWriterIndex + index, SeekOrigin.Begin); - planesWriter.Write(mte.ItemId); - continue; - } + size = height - 2; + x -= 1; + y -= 1; + } + else + { + size = height - 1; + plane += 4; } - planeOffsetWriter.Write(mte.ItemId); - planeOffsetWriter.Write((byte)mte.OffsetX); - planeOffsetWriter.Write((byte)mte.OffsetY); - planeOffsetWriter.Write((byte)mte.OffsetZ); - totalPlaneOffsets++; - } + index = (x * size + y) * 2; - var maxPlanesLength = (Zlib.MaxPackSize(planeLength) + 4) * totalPlanes; - var maxPlaneOffsetLength = totalPlaneOffsets == 0 ? 0 - : (maxPackedPlaneOffsetBuffer + 4) * (totalPlaneOffsets / maxPerPlaneOffsetBuffer + 1); - - var buffer = GC.AllocateUninitializedArray(18 + maxPlanesLength + maxPlaneOffsetLength); - var writer = new SpanWriter(buffer); - writer.Write((byte)0xD8); // Packet ID - writer.Seek(2, SeekOrigin.Current); // Length - - writer.Write((byte)0x03); // Compression Type - writer.Write((byte)0x00); // Unknown - writer.Write(serial); - writer.Write(revision); - writer.Write((short)tiles.Length); - writer.Seek(3, SeekOrigin.Current); // Buffer Length, Plane Count - - var totalLength = 1; // includes plane count - - for (var i = 0; i < planeCount; i++) - { - if (!planesUsed[i]) + if (x >= 0 && y >= 0 && y < size && index + 1 < maxPlaneLength) { + var planeUsed = planesUsed[plane]; + var planeWriterIndex = planeLength * plane; + if (!planeUsed) + { + planesUsed[plane] = true; + totalPlanes++; + planesWriter.Seek(planeWriterIndex, SeekOrigin.Begin); + planesWriter.Clear(planeLength); + } + + planesWriter.Seek(planeWriterIndex + index, SeekOrigin.Begin); + planesWriter.Write(mte.ItemId); continue; } - - int size = i switch - { - 0 => planeLength, - < 5 => (width - 1) * (height - 2) * 2, - _ => width * (height - 1) * 2 - }; - - var planeWriterIndex = planeLength * i; - - var source = planesWriter.RawBuffer.Slice(planeWriterIndex, size); - - writer.Write((byte)(0x20 | i)); - WritePacked(source, ref writer, out int destLength); - - totalLength += 4 + destLength; } - index = 0; - while (totalPlaneOffsets > 0) - { - var count = Math.Min(maxPerPlaneOffsetBuffer, totalPlaneOffsets); - totalPlaneOffsets -= count; - - var source = planeOffsetWriter.RawBuffer.Slice(index * 5, count * 5); - - writer.Write((byte)(9 + index++)); - WritePacked(source, ref writer, out int destLength); - totalLength += 4 + destLength; - totalPlanes++; - } - - writer.Seek(15, SeekOrigin.Begin); - writer.Write((short)totalLength); - writer.Write((byte)totalPlanes); - writer.WritePacketLength(); - - // TODO: Avoid this somehow. - Array.Resize(ref buffer, writer.BytesWritten); - return buffer; + planeOffsetWriter.Write(mte.ItemId); + planeOffsetWriter.Write((byte)mte.OffsetX); + planeOffsetWriter.Write((byte)mte.OffsetY); + planeOffsetWriter.Write((byte)mte.OffsetZ); + totalPlaneOffsets++; } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WritePacked(ReadOnlySpan source, ref SpanWriter writer, out int length) + var writer = new SpanWriter(0x10000); + writer.Write((byte)0xD8); // Packet ID + writer.Seek(2, SeekOrigin.Current); // Length + + writer.Write((byte)0x03); // Compression Type + writer.Write((byte)0x00); // Unknown + writer.Write(serial); + writer.Write(revision); + writer.Write((short)tiles.Length); + writer.Seek(3, SeekOrigin.Current); // Buffer Length, Plane Count + + var totalLength = 1; // includes plane count + + for (var i = 0; i < planeCount; i++) { - var size = source.Length; - var dest = writer.RawBuffer[(writer.Position + 3)..]; - length = dest.Length; - - var ce = Zlib.Pack(dest, ref length, source, ZlibQuality.Default); - - if (ce != ZlibError.Okay) + if (!planesUsed[i]) { - logger.Warning("ZLib error: {Error} (#{ErrorCode})", ce, (int)ce); - length = 0; - size = 0; + continue; } + int size = i switch + { + 0 => planeLength, + < 5 => (width - 1) * (height - 2) * 2, + _ => width * (height - 1) * 2 + }; + + var planeWriterIndex = planeLength * i; + + var source = planesWriter.RawBuffer.Slice(planeWriterIndex, size); + + writer.Write((byte)(0x20 | i)); writer.Write((byte)size); - writer.Write((byte)length); - writer.Write((byte)(((size >> 4) & 0xF0) | ((length >> 8) & 0xF))); - writer.Seek(length, SeekOrigin.Current); + WritePacked(source, ref writer, out int destLength); + + totalLength += 4 + destLength; } + + index = 0; + while (totalPlaneOffsets > 0) + { + var count = Math.Min(maxPerPlaneOffsetBuffer, totalPlaneOffsets); + totalPlaneOffsets -= count; + var size = count * 5; + + var source = planeOffsetWriter.RawBuffer.Slice(index * 5, size); + + writer.Write((byte)(9 + index++)); + writer.Write((byte)size); + WritePacked(source, ref writer, out int destLength); + totalLength += 4 + destLength; + totalPlanes++; + } + + writer.Seek(15, SeekOrigin.Begin); + writer.Write((short)totalLength); + writer.Write((byte)totalPlanes); + writer.WritePacketLength(); + + var buffer = writer.Span.ToArray(); + writer.Dispose(); + + return buffer; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WritePacked(ReadOnlySpan source, ref SpanWriter writer, out int length) + { + var size = source.Length; + var dest = writer.RawBuffer[(writer.Position + 2)..]; + + length = Deflate.Standard.Pack(dest, source); + + if (length == 0) + { + logger.Warning("House packet compression failed."); + } + + writer.Write((byte)length); + writer.Write((byte)(((size >> 4) & 0xF0) | ((length >> 8) & 0xF))); + writer.Seek(length, SeekOrigin.Current); } } diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj index 76d00e546..2a581ace4 100644 --- a/Projects/UOContent/UOContent.csproj +++ b/Projects/UOContent/UOContent.csproj @@ -24,7 +24,9 @@ - + + + @@ -32,10 +34,10 @@ false + - diff --git a/README.md b/README.md index 0ee87f55b..85876fcf6 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ ModernUO [![Discord](https://img.shields.io/discord/751317910504603701?logo=disc - Run `./publish.cmd [release|debug (default: release)] [os] [arch (default: x64)]` - `os` - [Supported operating systems](https://github.com/dotnet/core/blob/main/release-notes/7.0/supported-os.md) - `win` - Windows 10/11/2019/2022 - - `osx` - MacOS 11/12/13 (Big Sur, Monterey, Ventura) + - `osx` - MacOS 12/13/14 (Sonoma, Big Sur, Monterey) - `linux` - Linux - `arch` - `x64` - Intel 64-bit @@ -74,13 +74,18 @@ ModernUO [![Discord](https://img.shields.io/discord/751317910504603701?logo=disc dnf upgrade --refresh -y # CentOS does not come with EPEL enabled dnf install -y epel-release epel-next-release -dnf install -y findutils libicu zlib-devel zstd libargon2-devel tzdata +dnf install -y findutils libicu libdeflate-devel zstd libargon2-devel ``` ### Ubuntu, Debian, etc ```shell apt-get update -y -apt-get install -y libicu-dev libz-dev zstd libargon2-dev tzdata +apt-get install -y libicu-dev libdeflate-dev zstd libargon2-dev +``` + +## OSX Requirements +```shell +brew install icu4c libdeflate zstd argon2 ``` ## Running the Server diff --git a/version.json b/version.json index 49a4bfc02..4190f0de5 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.13.2" + "version": "0.13.3" }