fix(network): Converts House Design Detailed Packet (#538)
- [X] Converts design state detailed packet - [X] Removes `Packet` class - [X] Removes `Send(Packet)` function signatures - [X] Removes `PacketWriter` class - [X] Updates dependencies.
This commit is contained in:
parent
0a435644eb
commit
ec1cc10821
24 changed files with 538 additions and 463 deletions
2
.github/workflows/build-test.yml
vendored
2
.github/workflows/build-test.yml
vendored
|
|
@ -26,7 +26,7 @@ jobs:
|
|||
- name: Setup .NET 5
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.102
|
||||
dotnet-version: 5.0.200
|
||||
- name: Build
|
||||
run: ./publish.cmd
|
||||
- name: Test
|
||||
|
|
|
|||
|
|
@ -29,16 +29,16 @@
|
|||
<DefineConstants>MUO</DefineConstants>
|
||||
<GitVersionBaseDirectory>$(SolutionDir)</GitVersionBaseDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'==''">
|
||||
<PropertyGroup Condition="'$(RuntimeIdentifier)'==''">
|
||||
<DisableFastUpToDateCheck>true</DisableFastUpToDateCheck>
|
||||
<SelfContained>false</SelfContained>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<InvariantGlobalization>true</InvariantGlobalization>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsWindows)'=='true' AND '$(RuntimeIdentifier)'==''">
|
||||
<PropertyGroup Condition="'$(IsWindows)'=='true' AND '$(RuntimeIdentifier)'==''">
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(IsOSX)'=='true' AND '$(RuntimeIdentifier)'==''">
|
||||
<PropertyGroup Condition="'$(IsOSX)'=='true' AND '$(RuntimeIdentifier)'==''">
|
||||
<RuntimeIdentifier>osx-x64</RuntimeIdentifier>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)'=='Debug'">
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="Moq" Version="4.16.0" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.4.0" />
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ using System.IO;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Network;
|
||||
using Server.Text;
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.Serialization;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Accounting;
|
||||
using Server.Buffers;
|
||||
using Server.ContextMenus;
|
||||
|
|
@ -7047,24 +7047,6 @@ namespace Server
|
|||
eable.Free();
|
||||
}
|
||||
|
||||
public bool Send(Packet p) => Send(p, false);
|
||||
|
||||
public bool Send(Packet p, bool throwOnOffline)
|
||||
{
|
||||
if (m_NetState != null)
|
||||
{
|
||||
m_NetState.Send(p);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (throwOnOffline)
|
||||
{
|
||||
throw new MobileNotConnectedException(this, "Packet could not be sent.");
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overridable. Event invoked before the Mobile says something.
|
||||
/// <seealso cref="DoSpeech" />
|
||||
|
|
|
|||
|
|
@ -511,78 +511,6 @@ namespace Server.Network
|
|||
}
|
||||
}
|
||||
|
||||
public virtual void Send(Packet p)
|
||||
{
|
||||
if (Connection == null || BlockAllPackets)
|
||||
{
|
||||
p.OnSend();
|
||||
return;
|
||||
}
|
||||
|
||||
var writer = SendPipe.Writer;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] buffer = p.Compile(CompressionEnabled, out var length);
|
||||
|
||||
if (buffer == null)
|
||||
{
|
||||
WriteConsole("null buffer send, disconnecting...", this);
|
||||
using (StreamWriter op = new StreamWriter("null_send.log", true))
|
||||
{
|
||||
op.WriteLine("{0} Client: {1}: null buffer send, disconnecting...", DateTime.UtcNow, this);
|
||||
op.WriteLine(new System.Diagnostics.StackTrace());
|
||||
}
|
||||
|
||||
Disconnect("Attempted to send null packet buffer.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (buffer.Length <= 0 || length <= 0)
|
||||
{
|
||||
p.OnSend();
|
||||
return;
|
||||
}
|
||||
|
||||
PacketSendProfile prof = null;
|
||||
|
||||
if (Core.Profiling)
|
||||
{
|
||||
prof = PacketSendProfile.Acquire(p.PacketID);
|
||||
prof.Start();
|
||||
}
|
||||
|
||||
var result = writer.TryGetMemory();
|
||||
|
||||
if (result.Length >= length)
|
||||
{
|
||||
result.CopyFrom(buffer.AsSpan(0, length));
|
||||
writer.Advance((uint)length);
|
||||
|
||||
if (!_flushQueued)
|
||||
{
|
||||
FlushPending.Enqueue(this);
|
||||
_flushQueued = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteConsole("Too much data pending, disconnecting...");
|
||||
Disconnect("Too much data pending.");
|
||||
}
|
||||
|
||||
prof?.Finish(length);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
#if DEBUG
|
||||
Console.WriteLine(ex);
|
||||
#endif
|
||||
TraceException(ex);
|
||||
Disconnect("Exception while sending.");
|
||||
}
|
||||
}
|
||||
|
||||
internal void Start()
|
||||
{
|
||||
if (Interlocked.CompareExchange(ref _running, 1, 0) == 1 || Connection == null)
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
*************************************************************************/
|
||||
|
||||
using System.Diagnostics;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Diagnostics;
|
||||
using Server.Exceptions;
|
||||
using Server.Gumps;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ using System;
|
|||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Memory;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ namespace Server.Network
|
|||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public static void SendDeathStatus(this NetState ns, bool dead) =>
|
||||
ns?.Send(stackalloc byte[] { 0x2C, dead ? 0 : 2 });
|
||||
ns?.Send(stackalloc byte[] { 0x2C, dead ? (byte)0 : (byte)2 });
|
||||
|
||||
public static void SendToggleSpecialAbility(this NetState ns, int abilityId, bool active)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
<Delete Files="..\..\Distribution\$(AssemblyName).runtimeconfig.json" ContinueOnError="true" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.0-preview4" />
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.0-preview5" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.4.0" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ using System.Net.Sockets;
|
|||
using System.Runtime.CompilerServices;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Buffers;
|
||||
using Server.Network;
|
||||
using Server.Random;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Linq;
|
||||
using Server;
|
||||
using Server.Multis;
|
||||
using Server.Network;
|
||||
using Server.Tests;
|
||||
|
|
@ -48,5 +50,32 @@ namespace UOContent.Tests
|
|||
var result = ns.SendPipe.Reader.TryRead();
|
||||
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void TestHouseDesignStateDetailed()
|
||||
{
|
||||
Serial serial = 0x40000001;
|
||||
var revision = 10;
|
||||
var tiles = new MultiTileEntry[250];
|
||||
for (var i = 0; i < tiles.Length; i++)
|
||||
{
|
||||
tiles[i] = new MultiTileEntry(
|
||||
(ushort)i,
|
||||
(byte)i,
|
||||
(byte)i,
|
||||
(byte)(i / 50),
|
||||
TileFlag.None
|
||||
);
|
||||
}
|
||||
var mcl = new MultiComponentList(tiles.ToList());
|
||||
|
||||
var expected = new DesignStateDetailed(
|
||||
serial, revision, mcl.Min.X, mcl.Min.Y, mcl.Max.X, mcl.Max.Y, tiles
|
||||
).Compile();
|
||||
|
||||
var actual = HousePackets.CreateHouseDesignStateDetailed(serial, revision, mcl);
|
||||
|
||||
AssertThat.Equal(actual, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,9 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Server.Multis;
|
||||
|
||||
namespace Server.Network
|
||||
{
|
||||
public class BeginHouseCustomization : Packet
|
||||
|
|
@ -43,4 +49,287 @@ namespace Server.Network
|
|||
Stream.Write(revision);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DesignStateDetailed : Packet
|
||||
{
|
||||
public const int MaxItemsPerStairBuffer = 750;
|
||||
|
||||
private readonly bool[] m_PlaneUsed = new bool[9];
|
||||
private readonly byte[] m_PrimBuffer = new byte[4];
|
||||
|
||||
public DesignStateDetailed(uint serial, int revision, int xMin, int yMin, int xMax, int yMax, MultiTileEntry[] tiles)
|
||||
: base(0xD8)
|
||||
{
|
||||
EnsureCapacity(17 + tiles.Length * 5);
|
||||
|
||||
Write((byte)0x03); // Compression Type
|
||||
Write((byte)0x00); // Unknown
|
||||
Write(serial);
|
||||
Write(revision);
|
||||
Write((short)tiles.Length);
|
||||
Write((short)0); // Buffer length : reserved
|
||||
Write((byte)0); // Plane count : reserved
|
||||
|
||||
var totalLength = 1; // includes plane count
|
||||
|
||||
var width = xMax - xMin + 1;
|
||||
var height = yMax - yMin + 1;
|
||||
|
||||
var planeBuffers = new byte[9][];
|
||||
|
||||
for (var i = 0; i < planeBuffers.Length; ++i)
|
||||
{
|
||||
planeBuffers[i] = ArrayPool<byte>.Shared.Rent(0x400);
|
||||
}
|
||||
|
||||
var stairBuffers = new byte[6][];
|
||||
|
||||
for (var i = 0; i < stairBuffers.Length; ++i)
|
||||
{
|
||||
stairBuffers[i] = ArrayPool<byte>.Shared.Rent(MaxItemsPerStairBuffer * 5);
|
||||
}
|
||||
|
||||
Clear(planeBuffers[0], width * height * 2);
|
||||
|
||||
for (var i = 0; i < 4; ++i)
|
||||
{
|
||||
Clear(planeBuffers[1 + i], (width - 1) * (height - 2) * 2);
|
||||
Clear(planeBuffers[5 + i], width * (height - 1) * 2);
|
||||
}
|
||||
|
||||
var totalStairsUsed = 0;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
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;
|
||||
int plane, size;
|
||||
|
||||
switch (z)
|
||||
{
|
||||
case 0:
|
||||
plane = 0;
|
||||
break;
|
||||
case 7:
|
||||
plane = 1;
|
||||
break;
|
||||
case 27:
|
||||
plane = 2;
|
||||
break;
|
||||
case 47:
|
||||
plane = 3;
|
||||
break;
|
||||
case 67:
|
||||
plane = 4;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer;
|
||||
var stairBuffer = stairBuffers[stairBufferIndex];
|
||||
|
||||
var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8);
|
||||
stairBuffer[byteIndex++] = (byte)mte.ItemId;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetX;
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetY;
|
||||
stairBuffer[byteIndex] = (byte)mte.OffsetZ;
|
||||
|
||||
++totalStairsUsed;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (plane == 0)
|
||||
{
|
||||
size = height;
|
||||
}
|
||||
else if (floor)
|
||||
{
|
||||
size = height - 2;
|
||||
x -= 1;
|
||||
y -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = height - 1;
|
||||
plane += 4;
|
||||
}
|
||||
|
||||
var index = (x * size + y) * 2;
|
||||
|
||||
if (x < 0 || y < 0 || y >= size || index + 1 >= 0x400)
|
||||
{
|
||||
var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer;
|
||||
var stairBuffer = stairBuffers[stairBufferIndex];
|
||||
|
||||
var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8);
|
||||
stairBuffer[byteIndex++] = (byte)mte.ItemId;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetX;
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetY;
|
||||
stairBuffer[byteIndex] = (byte)mte.OffsetZ;
|
||||
|
||||
++totalStairsUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlaneUsed[plane] = true;
|
||||
planeBuffers[plane][index] = (byte)(mte.ItemId >> 8);
|
||||
planeBuffers[plane][index + 1] = (byte)mte.ItemId;
|
||||
}
|
||||
}
|
||||
|
||||
var planeCount = 0;
|
||||
|
||||
var deflatedBuffer = ArrayPool<byte>.Shared.Rent(0x2000);
|
||||
|
||||
for (var i = 0; i < planeBuffers.Length; ++i)
|
||||
{
|
||||
if (!m_PlaneUsed[i])
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(planeBuffers[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
++planeCount;
|
||||
|
||||
int size = i switch
|
||||
{
|
||||
0 => width * height * 2,
|
||||
< 5 => (width - 1) * (height - 2) * 2,
|
||||
_ => width * (height - 1) * 2
|
||||
};
|
||||
|
||||
var inflatedBuffer = planeBuffers[i];
|
||||
|
||||
var deflatedLength = deflatedBuffer.Length;
|
||||
var ce = Zlib.Pack(
|
||||
deflatedBuffer,
|
||||
ref deflatedLength,
|
||||
inflatedBuffer,
|
||||
size,
|
||||
ZlibQuality.Default
|
||||
);
|
||||
|
||||
if (ce != ZlibError.Okay)
|
||||
{
|
||||
Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
|
||||
deflatedLength = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
Write((byte)(0x20 | i));
|
||||
Write((byte)size);
|
||||
Write((byte)deflatedLength);
|
||||
Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)));
|
||||
Write(deflatedBuffer, 0, deflatedLength);
|
||||
|
||||
totalLength += 4 + deflatedLength;
|
||||
ArrayPool<byte>.Shared.Return(inflatedBuffer);
|
||||
}
|
||||
|
||||
var totalStairBuffersUsed = (totalStairsUsed + (MaxItemsPerStairBuffer - 1)) / MaxItemsPerStairBuffer;
|
||||
|
||||
for (var i = 0; i < totalStairBuffersUsed; ++i)
|
||||
{
|
||||
++planeCount;
|
||||
|
||||
var count = Math.Min(MaxItemsPerStairBuffer, totalStairsUsed - i * MaxItemsPerStairBuffer);
|
||||
|
||||
var size = count * 5;
|
||||
|
||||
var inflatedBuffer = stairBuffers[i];
|
||||
|
||||
var deflatedLength = deflatedBuffer.Length;
|
||||
var ce = Zlib.Pack(
|
||||
deflatedBuffer,
|
||||
ref deflatedLength,
|
||||
inflatedBuffer,
|
||||
size,
|
||||
ZlibQuality.Default
|
||||
);
|
||||
|
||||
if (ce != ZlibError.Okay)
|
||||
{
|
||||
Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
|
||||
deflatedLength = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
Write((byte)(9 + i));
|
||||
Write((byte)size);
|
||||
Write((byte)deflatedLength);
|
||||
Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)));
|
||||
Write(deflatedBuffer, 0, deflatedLength);
|
||||
|
||||
totalLength += 4 + deflatedLength;
|
||||
}
|
||||
|
||||
for (var i = 0; i < stairBuffers.Length; ++i)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(stairBuffers[i]);
|
||||
}
|
||||
|
||||
ArrayPool<byte>.Shared.Return(deflatedBuffer);
|
||||
|
||||
Stream.Seek(15, SeekOrigin.Begin);
|
||||
|
||||
Write((short)totalLength); // Buffer length
|
||||
Write((byte)planeCount); // Plane count
|
||||
}
|
||||
|
||||
public void Write(int value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 24);
|
||||
m_PrimBuffer[1] = (byte)(value >> 16);
|
||||
m_PrimBuffer[2] = (byte)(value >> 8);
|
||||
m_PrimBuffer[3] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4);
|
||||
}
|
||||
|
||||
public void Write(uint value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 24);
|
||||
m_PrimBuffer[1] = (byte)(value >> 16);
|
||||
m_PrimBuffer[2] = (byte)(value >> 8);
|
||||
m_PrimBuffer[3] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4);
|
||||
}
|
||||
|
||||
public void Write(short value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 8);
|
||||
m_PrimBuffer[1] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 2);
|
||||
}
|
||||
|
||||
public void Write(byte value)
|
||||
{
|
||||
Stream.UnderlyingStream.WriteByte(value);
|
||||
}
|
||||
|
||||
public void Write(byte[] buffer, int offset, int size)
|
||||
{
|
||||
Stream.UnderlyingStream.Write(buffer, offset, size);
|
||||
}
|
||||
|
||||
public static void Clear(byte[] buffer, int size)
|
||||
{
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
|
||||
<PackageReference Include="Moq" Version="4.16.0" />
|
||||
<PackageReference Include="Moq" Version="4.16.1" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" />
|
||||
<ProjectReference Include="..\Server\Server.csproj" />
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
|
||||
namespace Server
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
* ModernUO *
|
||||
* Copyright (C) 2019-2021 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: SpawnPropsGump.cs *
|
||||
* File: SpawnPropsCommand.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 *
|
||||
|
|
@ -21,14 +21,14 @@ using Server.Targeting;
|
|||
|
||||
namespace Server.Engines.Spawners
|
||||
{
|
||||
public class SpawnPropsGumpCommand : BaseCommand
|
||||
public class SpawnPropsCommand : BaseCommand
|
||||
{
|
||||
public static void Initialize()
|
||||
{
|
||||
TargetCommands.Register(new SpawnPropsGumpCommand());
|
||||
TargetCommands.Register(new SpawnPropsCommand());
|
||||
}
|
||||
|
||||
public SpawnPropsGumpCommand()
|
||||
public SpawnPropsCommand()
|
||||
{
|
||||
AccessLevel = AccessLevel.GameMaster;
|
||||
Supports = CommandSupport.Complex | CommandSupport.Simple;
|
||||
|
|
@ -3,6 +3,7 @@ using System.Buffers;
|
|||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Gumps;
|
||||
using Server.Items;
|
||||
using Server.Mobiles;
|
||||
|
|
@ -1872,8 +1873,6 @@ namespace Server.Multis
|
|||
|
||||
public class DesignState
|
||||
{
|
||||
private Packet m_PacketCache;
|
||||
|
||||
public DesignState(HouseFoundation foundation, MultiComponentList components)
|
||||
{
|
||||
Foundation = foundation;
|
||||
|
|
@ -1926,21 +1925,7 @@ namespace Server.Multis
|
|||
}
|
||||
}
|
||||
|
||||
public Packet PacketCache
|
||||
{
|
||||
get => m_PacketCache;
|
||||
set
|
||||
{
|
||||
if (m_PacketCache == value)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_PacketCache?.Release();
|
||||
|
||||
m_PacketCache = value;
|
||||
}
|
||||
}
|
||||
public byte[] PacketCache { get; set; }
|
||||
|
||||
public HouseFoundation Foundation { get; }
|
||||
|
||||
|
|
@ -1975,31 +1960,18 @@ namespace Server.Multis
|
|||
public void OnRevised()
|
||||
{
|
||||
Revision = ++Foundation.LastRevision;
|
||||
m_PacketCache?.Release();
|
||||
m_PacketCache = null;
|
||||
PacketCache = null;
|
||||
}
|
||||
|
||||
public void SendGeneralInfoTo(NetState state)
|
||||
{
|
||||
state.SendDesignStateGeneral(Foundation.Serial, Revision);
|
||||
}
|
||||
public void SendGeneralInfoTo(NetState state) => state.SendDesignStateGeneral(Foundation.Serial, Revision);
|
||||
public void SendDetailedInfoTo(NetState state) => state?.Send(PacketCache ??= SendDetails(Foundation.Serial));
|
||||
|
||||
public void SendDetailedInfoTo(NetState state)
|
||||
{
|
||||
if (state == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_PacketCache == null)
|
||||
{
|
||||
DesignStateDetailed.SendDetails(state, Foundation, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
state.Send(m_PacketCache);
|
||||
}
|
||||
}
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
public byte[] SendDetails(Serial house) => HousePackets.CreateHouseDesignStateDetailed(
|
||||
house,
|
||||
Revision,
|
||||
Components
|
||||
);
|
||||
|
||||
public void FreezeFixtures()
|
||||
{
|
||||
|
|
@ -2375,317 +2347,8 @@ namespace Server.Multis
|
|||
}
|
||||
|
||||
context.Foundation.Signpost?.SendInfoTo(state);
|
||||
|
||||
context.Foundation.SignHanger?.SendInfoTo(state);
|
||||
|
||||
context.Foundation.Sign?.SendInfoTo(state);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class DesignStateDetailed : Packet
|
||||
{
|
||||
public const int MaxItemsPerStairBuffer = 750;
|
||||
|
||||
private readonly bool[] m_PlaneUsed = new bool[9];
|
||||
private readonly byte[] m_PrimBuffer = new byte[4];
|
||||
|
||||
public DesignStateDetailed(uint serial, int revision, int xMin, int yMin, int xMax, int yMax, MultiTileEntry[] tiles)
|
||||
: base(0xD8)
|
||||
{
|
||||
EnsureCapacity(17 + tiles.Length * 5);
|
||||
|
||||
Write((byte)0x03); // Compression Type
|
||||
Write((byte)0x00); // Unknown
|
||||
Write(serial);
|
||||
Write(revision);
|
||||
Write((short)tiles.Length);
|
||||
Write((short)0); // Buffer length : reserved
|
||||
Write((byte)0); // Plane count : reserved
|
||||
|
||||
var totalLength = 1; // includes plane count
|
||||
|
||||
var width = xMax - xMin + 1;
|
||||
var height = yMax - yMin + 1;
|
||||
|
||||
var planeBuffers = new byte[9][];
|
||||
|
||||
for (var i = 0; i < planeBuffers.Length; ++i)
|
||||
{
|
||||
planeBuffers[i] = ArrayPool<byte>.Shared.Rent(0x400);
|
||||
}
|
||||
|
||||
var stairBuffers = new byte[6][];
|
||||
|
||||
for (var i = 0; i < stairBuffers.Length; ++i)
|
||||
{
|
||||
stairBuffers[i] = ArrayPool<byte>.Shared.Rent(MaxItemsPerStairBuffer * 5);
|
||||
}
|
||||
|
||||
Clear(planeBuffers[0], width * height * 2);
|
||||
|
||||
for (var i = 0; i < 4; ++i)
|
||||
{
|
||||
Clear(planeBuffers[1 + i], (width - 1) * (height - 2) * 2);
|
||||
Clear(planeBuffers[5 + i], width * (height - 1) * 2);
|
||||
}
|
||||
|
||||
var totalStairsUsed = 0;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
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;
|
||||
int plane, size;
|
||||
|
||||
switch (z)
|
||||
{
|
||||
case 0:
|
||||
plane = 0;
|
||||
break;
|
||||
case 7:
|
||||
plane = 1;
|
||||
break;
|
||||
case 27:
|
||||
plane = 2;
|
||||
break;
|
||||
case 47:
|
||||
plane = 3;
|
||||
break;
|
||||
case 67:
|
||||
plane = 4;
|
||||
break;
|
||||
default:
|
||||
{
|
||||
var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer;
|
||||
var stairBuffer = stairBuffers[stairBufferIndex];
|
||||
|
||||
var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8);
|
||||
stairBuffer[byteIndex++] = (byte)mte.ItemId;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetX;
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetY;
|
||||
stairBuffer[byteIndex] = (byte)mte.OffsetZ;
|
||||
|
||||
++totalStairsUsed;
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (plane == 0)
|
||||
{
|
||||
size = height;
|
||||
}
|
||||
else if (floor)
|
||||
{
|
||||
size = height - 2;
|
||||
x -= 1;
|
||||
y -= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
size = height - 1;
|
||||
plane += 4;
|
||||
}
|
||||
|
||||
var index = (x * size + y) * 2;
|
||||
|
||||
if (x < 0 || y < 0 || y >= size || index + 1 >= 0x400)
|
||||
{
|
||||
var stairBufferIndex = totalStairsUsed / MaxItemsPerStairBuffer;
|
||||
var stairBuffer = stairBuffers[stairBufferIndex];
|
||||
|
||||
var byteIndex = totalStairsUsed % MaxItemsPerStairBuffer * 5;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)(mte.ItemId >> 8);
|
||||
stairBuffer[byteIndex++] = (byte)mte.ItemId;
|
||||
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetX;
|
||||
stairBuffer[byteIndex++] = (byte)mte.OffsetY;
|
||||
stairBuffer[byteIndex] = (byte)mte.OffsetZ;
|
||||
|
||||
++totalStairsUsed;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_PlaneUsed[plane] = true;
|
||||
planeBuffers[plane][index] = (byte)(mte.ItemId >> 8);
|
||||
planeBuffers[plane][index + 1] = (byte)mte.ItemId;
|
||||
}
|
||||
}
|
||||
|
||||
var planeCount = 0;
|
||||
|
||||
var deflatedBuffer = ArrayPool<byte>.Shared.Rent(0x2000);
|
||||
|
||||
for (var i = 0; i < planeBuffers.Length; ++i)
|
||||
{
|
||||
if (!m_PlaneUsed[i])
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(planeBuffers[i]);
|
||||
continue;
|
||||
}
|
||||
|
||||
++planeCount;
|
||||
|
||||
int size = i switch
|
||||
{
|
||||
0 => width * height * 2,
|
||||
< 5 => (width - 1) * (height - 2) * 2,
|
||||
_ => width * (height - 1) * 2
|
||||
};
|
||||
|
||||
var inflatedBuffer = planeBuffers[i];
|
||||
|
||||
var deflatedLength = deflatedBuffer.Length;
|
||||
var ce = Zlib.Pack(
|
||||
deflatedBuffer,
|
||||
ref deflatedLength,
|
||||
inflatedBuffer,
|
||||
size,
|
||||
ZlibQuality.Default
|
||||
);
|
||||
|
||||
if (ce != ZlibError.Okay)
|
||||
{
|
||||
Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
|
||||
deflatedLength = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
Write((byte)(0x20 | i));
|
||||
Write((byte)size);
|
||||
Write((byte)deflatedLength);
|
||||
Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)));
|
||||
Write(deflatedBuffer, 0, deflatedLength);
|
||||
|
||||
totalLength += 4 + deflatedLength;
|
||||
ArrayPool<byte>.Shared.Return(inflatedBuffer);
|
||||
}
|
||||
|
||||
var totalStairBuffersUsed = (totalStairsUsed + (MaxItemsPerStairBuffer - 1)) / MaxItemsPerStairBuffer;
|
||||
|
||||
for (var i = 0; i < totalStairBuffersUsed; ++i)
|
||||
{
|
||||
++planeCount;
|
||||
|
||||
var count = Math.Min(MaxItemsPerStairBuffer, totalStairsUsed - i * MaxItemsPerStairBuffer);
|
||||
|
||||
var size = count * 5;
|
||||
|
||||
var inflatedBuffer = stairBuffers[i];
|
||||
|
||||
var deflatedLength = deflatedBuffer.Length;
|
||||
var ce = Zlib.Pack(
|
||||
deflatedBuffer,
|
||||
ref deflatedLength,
|
||||
inflatedBuffer,
|
||||
size,
|
||||
ZlibQuality.Default
|
||||
);
|
||||
|
||||
if (ce != ZlibError.Okay)
|
||||
{
|
||||
Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
|
||||
deflatedLength = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
Write((byte)(9 + i));
|
||||
Write((byte)size);
|
||||
Write((byte)deflatedLength);
|
||||
Write((byte)(((size >> 4) & 0xF0) | ((deflatedLength >> 8) & 0xF)));
|
||||
Write(deflatedBuffer, 0, deflatedLength);
|
||||
|
||||
totalLength += 4 + deflatedLength;
|
||||
}
|
||||
|
||||
for (var i = 0; i < stairBuffers.Length; ++i)
|
||||
{
|
||||
ArrayPool<byte>.Shared.Return(stairBuffers[i]);
|
||||
}
|
||||
|
||||
ArrayPool<byte>.Shared.Return(deflatedBuffer);
|
||||
|
||||
Stream.Seek(15, SeekOrigin.Begin);
|
||||
|
||||
Write((short)totalLength); // Buffer length
|
||||
Write((byte)planeCount); // Plane count
|
||||
}
|
||||
|
||||
public void Write(int value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 24);
|
||||
m_PrimBuffer[1] = (byte)(value >> 16);
|
||||
m_PrimBuffer[2] = (byte)(value >> 8);
|
||||
m_PrimBuffer[3] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4);
|
||||
}
|
||||
|
||||
public void Write(uint value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 24);
|
||||
m_PrimBuffer[1] = (byte)(value >> 16);
|
||||
m_PrimBuffer[2] = (byte)(value >> 8);
|
||||
m_PrimBuffer[3] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 4);
|
||||
}
|
||||
|
||||
public void Write(short value)
|
||||
{
|
||||
m_PrimBuffer[0] = (byte)(value >> 8);
|
||||
m_PrimBuffer[1] = (byte)value;
|
||||
|
||||
Stream.UnderlyingStream.Write(m_PrimBuffer, 0, 2);
|
||||
}
|
||||
|
||||
public void Write(byte value)
|
||||
{
|
||||
Stream.UnderlyingStream.WriteByte(value);
|
||||
}
|
||||
|
||||
public void Write(byte[] buffer, int offset, int size)
|
||||
{
|
||||
Stream.UnderlyingStream.Write(buffer, offset, size);
|
||||
}
|
||||
|
||||
public static void Clear(byte[] buffer, int size)
|
||||
{
|
||||
for (var i = 0; i < size; ++i)
|
||||
{
|
||||
buffer[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SendDetails(NetState ns, HouseFoundation house, DesignState state)
|
||||
{
|
||||
var p = state.PacketCache;
|
||||
|
||||
if (p == null)
|
||||
{
|
||||
var mcl = state.Components;
|
||||
p = new DesignStateDetailed(
|
||||
house.Serial,
|
||||
state.Revision,
|
||||
mcl.Min.X,
|
||||
mcl.Min.Y,
|
||||
mcl.Max.X,
|
||||
mcl.Max.Y,
|
||||
mcl.List
|
||||
);
|
||||
|
||||
p.SetStatic();
|
||||
state.PacketCache = p;
|
||||
}
|
||||
|
||||
ns.Send(p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,15 +13,17 @@
|
|||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Network;
|
||||
|
||||
namespace Server.Multis
|
||||
{
|
||||
public static class HousePackets
|
||||
{
|
||||
private const int MaxItemsPerStairBuffer = 750;
|
||||
|
||||
public static void SendBeginHouseCustomization(this NetState ns, Serial house)
|
||||
{
|
||||
if (ns == null)
|
||||
|
|
@ -80,5 +82,187 @@ namespace Server.Multis
|
|||
|
||||
ns.Send(writer.Span);
|
||||
}
|
||||
|
||||
private const int planeCount = 9;
|
||||
private const int planeLength = 0x400; // ItemID (max 1024 items per plane within the design grid)
|
||||
private const int stairsCount = 6;
|
||||
private const int stairsLength = 5; // ItemID, X, Y, Z (max 4500 items)
|
||||
private const int stairsPerBuffer = 750;
|
||||
|
||||
// Maximum size of the packed packet (31988 bytes)
|
||||
private static readonly int maxPacketLength =
|
||||
18 +
|
||||
(Zlib.MaxPackSize(planeLength) + 4) * planeCount + // 9369
|
||||
(Zlib.MaxPackSize(stairsPerBuffer * stairsLength) + 4) * stairsCount; // 22602
|
||||
|
||||
public static byte[] CreateHouseDesignStateDetailed(uint 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 tiles = components.List;
|
||||
|
||||
const int totalPlaneLength = planeLength * planeCount;
|
||||
const int stairsBufferLength = stairsPerBuffer * stairsLength;
|
||||
const int maxUnpackedSize = totalPlaneLength + stairsBufferLength * stairsCount;
|
||||
using var inflatedWriter = new SpanWriter(maxUnpackedSize);
|
||||
|
||||
Span<bool> planesUsed = stackalloc bool[9];
|
||||
var index = 0;
|
||||
var stairsIndex = totalPlaneLength;
|
||||
var totalStairsUsed = 0;
|
||||
var width = xMax - xMin + 1;
|
||||
var height = yMax - yMin + 1;
|
||||
|
||||
for (var i = 0; i < tiles.Length; ++i)
|
||||
{
|
||||
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;
|
||||
|
||||
int plane = z switch
|
||||
{
|
||||
0 => 0,
|
||||
7 => 1,
|
||||
27 => 2,
|
||||
47 => 3,
|
||||
67 => 4,
|
||||
_ => -1
|
||||
};
|
||||
|
||||
if (plane > -1)
|
||||
{
|
||||
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 < 0x400)
|
||||
{
|
||||
var planeUsed = planesUsed[plane];
|
||||
if (!planeUsed)
|
||||
{
|
||||
inflatedWriter.Seek(plane * planeLength, SeekOrigin.Begin);
|
||||
inflatedWriter.Clear(planeLength);
|
||||
planesUsed[plane] = true;
|
||||
}
|
||||
|
||||
inflatedWriter.Seek(index, SeekOrigin.Begin);
|
||||
inflatedWriter.Write(mte.ItemId);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
inflatedWriter.Seek(stairsIndex, SeekOrigin.Begin);
|
||||
inflatedWriter.Write(mte.ItemId);
|
||||
inflatedWriter.Write((byte)mte.OffsetX);
|
||||
inflatedWriter.Write((byte)mte.OffsetY);
|
||||
inflatedWriter.Write((byte)mte.OffsetZ);
|
||||
stairsIndex = inflatedWriter.Position;
|
||||
totalStairsUsed++;
|
||||
}
|
||||
|
||||
var buffer = GC.AllocateUninitializedArray<byte>(maxPacketLength);
|
||||
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 totalPlanes = 0;
|
||||
var totalLength = 1; // includes plane count
|
||||
|
||||
for (var i = 0; i < planeCount; i++)
|
||||
{
|
||||
if (!planesUsed[i])
|
||||
{
|
||||
inflatedWriter.Seek(planeCount, SeekOrigin.Current);
|
||||
continue;
|
||||
}
|
||||
|
||||
int size = i switch
|
||||
{
|
||||
0 => width * height * 2,
|
||||
< 5 => (width - 1) * (height - 2) * 2,
|
||||
_ => width * (height - 1) * 2
|
||||
};
|
||||
|
||||
var source = inflatedWriter.RawBuffer.Slice(i * planeLength, size);
|
||||
|
||||
writer.Write((byte)(0x20 | i));
|
||||
WritePacked(source, ref writer, out int destLength);
|
||||
|
||||
totalLength += 4 + destLength;
|
||||
totalPlanes++;
|
||||
}
|
||||
|
||||
index = 0;
|
||||
while (totalStairsUsed > 0)
|
||||
{
|
||||
var count = Math.Min(stairsPerBuffer, totalStairsUsed);
|
||||
totalStairsUsed -= count;
|
||||
|
||||
var start = totalPlaneLength + index * stairsLength;
|
||||
var size = count * 5;
|
||||
var source = inflatedWriter.RawBuffer.Slice(start, size);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
private static void WritePacked(ReadOnlySpan<byte> source, ref SpanWriter writer, out int length)
|
||||
{
|
||||
var size = source.Length;
|
||||
var dest = writer.RawBuffer.Slice(writer.Position + 3);
|
||||
length = dest.Length;
|
||||
|
||||
var ce = Zlib.Pack(dest, ref length, source, ZlibQuality.Default);
|
||||
|
||||
if (ce != ZlibError.Okay)
|
||||
{
|
||||
Console.WriteLine("ZLib error: {0} (#{1})", ce, (int)ce);
|
||||
length = 0;
|
||||
size = 0;
|
||||
}
|
||||
|
||||
writer.Write((byte)size);
|
||||
writer.Write((byte)length);
|
||||
writer.Write((byte)(((size >> 4) & 0xF0) | ((length >> 8) & 0xF)));
|
||||
writer.Seek(length, SeekOrigin.Current);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using System.Text;
|
||||
using Microsoft.Toolkit.HighPerformance.Extensions;
|
||||
using Microsoft.Toolkit.HighPerformance;
|
||||
using Server.Commands;
|
||||
using Server.Gumps;
|
||||
using Server.Network;
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
<IncludeInPackage>false</IncludeInPackage>
|
||||
</ProjectReference>
|
||||
<PackageReference Include="MailKit" Version="2.10.1" />
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.0-preview4" />
|
||||
<PackageReference Include="Microsoft.Toolkit.HighPerformance" Version="7.0.0-preview5" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.4.0" />
|
||||
<PackageReference Include="Argon2.Bindings" Version="1.8.0" />
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ jobs:
|
|||
displayName: 'Install .NET 5'
|
||||
inputs:
|
||||
packageType: sdk
|
||||
version: '5.0.102'
|
||||
version: 5.0.200
|
||||
- task: NuGetAuthenticate@0
|
||||
- script: ./publish.cmd Release win
|
||||
displayName: 'Build'
|
||||
|
|
@ -56,7 +56,7 @@ jobs:
|
|||
displayName: 'Install .NET 5'
|
||||
inputs:
|
||||
packageType: sdk
|
||||
version: '5.0.102'
|
||||
version: 5.0.200
|
||||
- task: NuGetAuthenticate@0
|
||||
- script: ./publish.cmd Release $(os)
|
||||
displayName: 'Build'
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue