fix(core): Converts vendor buy packets (#339)
This commit is contained in:
parent
d71856ddbe
commit
5e991f6fb5
10 changed files with 255 additions and 513 deletions
|
|
@ -1,157 +0,0 @@
|
||||||
using System;
|
|
||||||
using System.Buffers;
|
|
||||||
using System.Buffers.Binary;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using BenchmarkDotNet.Attributes;
|
|
||||||
using BenchmarkDotNet.Jobs;
|
|
||||||
using Server;
|
|
||||||
using Server.Network;
|
|
||||||
|
|
||||||
namespace Benchmarks
|
|
||||||
{
|
|
||||||
[SimpleJob(RuntimeMoniker.NetCoreApp50)]
|
|
||||||
public class BenchmarkPacketConstruction
|
|
||||||
{
|
|
||||||
public List<BuyItemState> m_States;
|
|
||||||
|
|
||||||
[GlobalSetup]
|
|
||||||
public void SetUp()
|
|
||||||
{
|
|
||||||
m_States = new List<BuyItemState>
|
|
||||||
{
|
|
||||||
new("Name 1", 0x1000, 0x2000, 1000, 1, 10, 1024),
|
|
||||||
new("Name 2", 0x1001, 0x2001, 1001, 1, 10, 1024),
|
|
||||||
new("Name 3", 0x1002, 0x2002, 1002, 1, 10, 1024),
|
|
||||||
new("Name 4", 0x1003, 0x2003, 1003, 1, 10, 1024),
|
|
||||||
new("Name 5", 0x1004, 0x2004, 1004, 1, 10, 1024),
|
|
||||||
new("Name 6", 0x1005, 0x2005, 1005, 1, 10, 1024),
|
|
||||||
new("Name 7", 0x1006, 0x2006, 1006, 1, 10, 1024),
|
|
||||||
new("Name 8", 0x1007, 0x2007, 1007, 1, 10, 1024),
|
|
||||||
new("Name 9", 0x1008, 0x2008, 1008, 1, 10, 1024),
|
|
||||||
new("Name A", 0x1009, 0x2009, 1009, 1, 10, 1024),
|
|
||||||
new("Name 10", 0x1000, 0x2000, 1000, 1, 10, 1024),
|
|
||||||
new("Name 20", 0x1001, 0x2001, 1001, 1, 10, 1024),
|
|
||||||
new("Name 30", 0x1002, 0x2002, 1002, 1, 10, 1024),
|
|
||||||
new("Name 40", 0x1003, 0x2003, 1003, 1, 10, 1024),
|
|
||||||
new("Name 50", 0x1004, 0x2004, 1004, 1, 10, 1024),
|
|
||||||
new("Name 60", 0x1005, 0x2005, 1005, 1, 10, 1024),
|
|
||||||
new("Name 70", 0x1006, 0x2006, 1006, 1, 10, 1024),
|
|
||||||
new("Name 80", 0x1007, 0x2007, 1007, 1, 10, 1024),
|
|
||||||
new("Name 90", 0x1008, 0x2008, 1008, 1, 10, 1024),
|
|
||||||
new("Name A0", 0x1009, 0x2009, 1009, 1, 10, 1024),
|
|
||||||
new("Name 11", 0x1000, 0x2000, 1000, 1, 10, 1024),
|
|
||||||
new("Name 21", 0x1001, 0x2001, 1001, 1, 10, 1024),
|
|
||||||
new("Name 31", 0x1002, 0x2002, 1002, 1, 10, 1024),
|
|
||||||
new("Name 41", 0x1003, 0x2003, 1003, 1, 10, 1024),
|
|
||||||
new("Name 51", 0x1004, 0x2004, 1004, 1, 10, 1024),
|
|
||||||
new("Name 61", 0x1005, 0x2005, 1005, 1, 10, 1024),
|
|
||||||
new("Name 71", 0x1006, 0x2006, 1006, 1, 10, 1024),
|
|
||||||
new("Name 81", 0x1007, 0x2007, 1007, 1, 10, 1024),
|
|
||||||
new("Name 91", 0x1008, 0x2008, 1008, 1, 10, 1024),
|
|
||||||
new("Name A1", 0x1009, 0x2009, 1009, 1, 10, 1024)
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public Packet TestPacketConstruction()
|
|
||||||
{
|
|
||||||
Packet p = new VendorBuyContent(m_States);
|
|
||||||
p.Compile(false, out _);
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public int TestInlineRefConstruction()
|
|
||||||
{
|
|
||||||
var buyStates = m_States;
|
|
||||||
|
|
||||||
int length = 5 + buyStates.Count * 19;
|
|
||||||
|
|
||||||
Span<byte> data = stackalloc byte[length];
|
|
||||||
|
|
||||||
int pos = 0;
|
|
||||||
data.Write(ref pos, (byte)0x3C);
|
|
||||||
data.Write(ref pos, (ushort)length);
|
|
||||||
data.Write(ref pos, (ushort)buyStates.Count);
|
|
||||||
|
|
||||||
for (int i = buyStates.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
BuyItemState buyState = buyStates[i];
|
|
||||||
|
|
||||||
data.Write(ref pos, buyState.MySerial);
|
|
||||||
data.Write(ref pos, (ushort)buyState.ItemID);
|
|
||||||
data.Write(ref pos, (byte)0);
|
|
||||||
data.Write(ref pos, (ushort)buyState.Amount);
|
|
||||||
data.Write(ref pos, (ushort)(i + 1));
|
|
||||||
data.Write(ref pos, (ushort)0x1);
|
|
||||||
data.Write(ref pos, buyState.ContainerSerial);
|
|
||||||
data.Write(ref pos, (ushort)buyState.Hue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public int TestInlineConstruction()
|
|
||||||
{
|
|
||||||
var buyStates = m_States;
|
|
||||||
|
|
||||||
Span<byte> data = stackalloc byte[5 + buyStates.Count * 19];
|
|
||||||
data[0] = 0x3C;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(1, 2), (ushort)data.Length);
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(3, 2), (ushort)buyStates.Count);
|
|
||||||
int pos = 4;
|
|
||||||
|
|
||||||
|
|
||||||
for (int i = buyStates.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
BuyItemState buyState = buyStates[i];
|
|
||||||
BinaryPrimitives.WriteUInt32BigEndian(data.Slice(pos, 4), buyState.MySerial);
|
|
||||||
pos += 4;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(pos, 2), (ushort)buyState.ItemID);
|
|
||||||
pos += 2;
|
|
||||||
data[pos++] = 0;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(pos, 2), (ushort)buyState.Amount);
|
|
||||||
pos += 2;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(pos, 2), (ushort)(i + 1));
|
|
||||||
pos += 2;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(pos, 2), 0x1);
|
|
||||||
pos += 2;
|
|
||||||
BinaryPrimitives.WriteUInt32BigEndian(data.Slice(pos, 4), buyState.ContainerSerial);
|
|
||||||
pos += 4;
|
|
||||||
BinaryPrimitives.WriteUInt16BigEndian(data.Slice(pos, 2), (ushort)(buyState.Hue));
|
|
||||||
pos += 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.Length;
|
|
||||||
}
|
|
||||||
|
|
||||||
[Benchmark]
|
|
||||||
public int TestSpanWriterConstruction()
|
|
||||||
{
|
|
||||||
var buyStates = m_States;
|
|
||||||
|
|
||||||
int length = 5 + buyStates.Count * 19;
|
|
||||||
|
|
||||||
SpanWriter w = new SpanWriter(stackalloc byte[length]);
|
|
||||||
|
|
||||||
w.Write((byte)0x3C); // Packet ID
|
|
||||||
w.Write((ushort)length); // Length
|
|
||||||
w.Write((ushort)buyStates.Count); // Length
|
|
||||||
|
|
||||||
for (int i = buyStates.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
BuyItemState buyState = buyStates[i];
|
|
||||||
w.Write(buyState.MySerial);
|
|
||||||
w.Write((ushort)buyState.ItemID);
|
|
||||||
w.Write((byte)0);
|
|
||||||
w.Write((ushort)(i + 1)); // X
|
|
||||||
w.Write((ushort)0x1); // Y
|
|
||||||
w.Write(buyState.ContainerSerial);
|
|
||||||
w.Write((ushort)buyState.Hue);
|
|
||||||
}
|
|
||||||
|
|
||||||
return w.Position;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -2,6 +2,7 @@ using System;
|
||||||
using System.Buffers;
|
using System.Buffers;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using Server.Items;
|
using Server.Items;
|
||||||
using Server.Network;
|
using Server.Network;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
@ -10,8 +11,10 @@ namespace Server.Tests.Network
|
||||||
{
|
{
|
||||||
public class VendorBuyPacketTests : IClassFixture<ServerFixture>
|
public class VendorBuyPacketTests : IClassFixture<ServerFixture>
|
||||||
{
|
{
|
||||||
[Fact]
|
[Theory]
|
||||||
public void TestVendorBuyContent()
|
[InlineData(ProtocolChanges.None)]
|
||||||
|
[InlineData(ProtocolChanges.ContainerGridLines)]
|
||||||
|
public void TestVendorBuyContent(ProtocolChanges protocolChanges)
|
||||||
{
|
{
|
||||||
var cont = new Container(World.NewItem);
|
var cont = new Container(World.NewItem);
|
||||||
|
|
||||||
|
|
@ -22,115 +25,34 @@ namespace Server.Tests.Network
|
||||||
new("Third Item", cont.Serial, World.NewItem, 30, 10, 0x0F, 0)
|
new("Third Item", cont.Serial, World.NewItem, 30, 10, 0x0F, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
var data = new VendorBuyContent(buyStates).Compile();
|
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||||
|
ns.ProtocolChanges = protocolChanges;
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[5 + buyStates.Count * 19];
|
var expected = new VendorBuyContent(buyStates, ns.ContainerGridLines).Compile();
|
||||||
|
|
||||||
var pos = 0;
|
ns.SendVendorBuyContent(buyStates);
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
|
var result = ns.SendPipe.Reader.TryRead();
|
||||||
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
|
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||||
expectedData.Write(ref pos, (ushort)buyStates.Count); // Count
|
|
||||||
|
|
||||||
for (var i = buyStates.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var buyState = buyStates[i];
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, buyState.MySerial);
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.ItemID);
|
|
||||||
pos++; // ItemID Offset
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.Amount);
|
|
||||||
expectedData.Write(ref pos, (ushort)(i + 1)); // X
|
|
||||||
expectedData.Write(ref pos, (ushort)1); // Y
|
|
||||||
expectedData.Write(ref pos, buyState.ContainerSerial);
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.Hue);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Theory]
|
||||||
public void TestVendorBuyContent6017()
|
[InlineData(ProtocolChanges.None)]
|
||||||
{
|
[InlineData(ProtocolChanges.HighSeas)]
|
||||||
var cont = new Container(World.NewItem);
|
public void TestDisplayBuyList(ProtocolChanges protocolChanges)
|
||||||
|
|
||||||
var buyStates = new List<BuyItemState>
|
|
||||||
{
|
|
||||||
new("First Item", cont.Serial, World.NewItem, 10, 1, 0x01, 0),
|
|
||||||
new("Second Item", cont.Serial, World.NewItem, 20, 2, 0x0A, 0),
|
|
||||||
new("Third Item", cont.Serial, World.NewItem, 30, 10, 0x0F, 0)
|
|
||||||
};
|
|
||||||
|
|
||||||
var data = new VendorBuyContent6017(buyStates).Compile();
|
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[5 + buyStates.Count * 20];
|
|
||||||
|
|
||||||
var pos = 0;
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x3C); // Packet ID
|
|
||||||
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
|
|
||||||
expectedData.Write(ref pos, (ushort)buyStates.Count); // Count
|
|
||||||
|
|
||||||
for (var i = buyStates.Count - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var buyState = buyStates[i];
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, buyState.MySerial);
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.ItemID);
|
|
||||||
pos++; // ItemID Offset
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.Amount);
|
|
||||||
expectedData.Write(ref pos, (ushort)(i + 1)); // X
|
|
||||||
expectedData.Write(ref pos, (ushort)1); // Y
|
|
||||||
#if NO_LOCAL_INIT
|
|
||||||
expectedData.Write(ref pos, (byte)0); // Grid Location?
|
|
||||||
#else
|
|
||||||
pos++;
|
|
||||||
#endif
|
|
||||||
expectedData.Write(ref pos, buyState.ContainerSerial);
|
|
||||||
expectedData.Write(ref pos, (ushort)buyState.Hue);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void TestDisplayBuyList()
|
|
||||||
{
|
{
|
||||||
var vendor = new Mobile(0x1);
|
var vendor = new Mobile(0x1);
|
||||||
vendor.DefaultMobileInit();
|
vendor.DefaultMobileInit();
|
||||||
|
|
||||||
var data = new DisplayBuyList(vendor).Compile();
|
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||||
|
ns.ProtocolChanges = protocolChanges;
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[7];
|
var expected = new DisplayBuyList(vendor.Serial, ns.HighSeas).Compile();
|
||||||
var pos = 0;
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x24); // Packet ID
|
ns.SendDisplayBuyList(vendor.Serial);
|
||||||
expectedData.Write(ref pos, vendor.Serial);
|
|
||||||
expectedData.Write(ref pos, (ushort)0x30); // Buy gump
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
var result = ns.SendPipe.Reader.TryRead();
|
||||||
}
|
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||||
|
|
||||||
[Fact]
|
|
||||||
public void TestDisplayBuyListHS()
|
|
||||||
{
|
|
||||||
var vendor = new Mobile(0x1);
|
|
||||||
vendor.DefaultMobileInit();
|
|
||||||
|
|
||||||
var data = new DisplayBuyListHS(vendor).Compile();
|
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[9];
|
|
||||||
var pos = 0;
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x24); // Packet ID
|
|
||||||
expectedData.Write(ref pos, vendor.Serial);
|
|
||||||
expectedData.Write(ref pos, (ushort)0x30); // Buy gump
|
|
||||||
|
|
||||||
#if NO_LOCAL_INIT
|
|
||||||
expectedData.Write(ref pos, (ushort)0);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -148,29 +70,13 @@ namespace Server.Tests.Network
|
||||||
new("Third Item", cont.Serial, World.NewItem, 30, 10, 0x0F, 0)
|
new("Third Item", cont.Serial, World.NewItem, 30, 10, 0x0F, 0)
|
||||||
};
|
};
|
||||||
|
|
||||||
var data = new VendorBuyList(vendor, buyStates).Compile();
|
var expected = new VendorBuyList(vendor, buyStates).Compile();
|
||||||
|
|
||||||
var length = 8 + buyStates.Sum(state => 6 + state.Description.Length);
|
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||||
|
ns.SendVendorBuyList(vendor, buyStates);
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[length];
|
var result = ns.SendPipe.Reader.TryRead();
|
||||||
|
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||||
var pos = 0;
|
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x74); // Packet ID
|
|
||||||
expectedData.Write(ref pos, (ushort)expectedData.Length); // Length
|
|
||||||
expectedData.Write(ref pos, Serial.MinusOne); // Vendor Buy Pack Serial or -1
|
|
||||||
expectedData.Write(ref pos, (byte)buyStates.Count);
|
|
||||||
|
|
||||||
for (var i = 0; i < buyStates.Count; i++)
|
|
||||||
{
|
|
||||||
var state = buyStates[i];
|
|
||||||
expectedData.Write(ref pos, state.Price);
|
|
||||||
var description = state.Description ?? "";
|
|
||||||
expectedData.Write(ref pos, (byte)Math.Min(255, description.Length + 1));
|
|
||||||
expectedData.WriteAsciiNull(ref pos, description, 255);
|
|
||||||
}
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|
@ -179,20 +85,13 @@ namespace Server.Tests.Network
|
||||||
var vendor = new Mobile(0x1);
|
var vendor = new Mobile(0x1);
|
||||||
vendor.DefaultMobileInit();
|
vendor.DefaultMobileInit();
|
||||||
|
|
||||||
var data = new EndVendorBuy(vendor).Compile();
|
var expected = new EndVendorBuy(vendor.Serial).Compile();
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[8];
|
using var ns = PacketTestUtilities.CreateTestNetState();
|
||||||
var pos = 0;
|
ns.SendEndVendorBuy(vendor.Serial);
|
||||||
|
|
||||||
expectedData.Write(ref pos, (byte)0x3B); // Packet ID
|
var result = ns.SendPipe.Reader.TryRead();
|
||||||
expectedData.Write(ref pos, (ushort)0x8); // Length
|
AssertThat.Equal(result.Buffer[0].AsSpan(0), expected);
|
||||||
expectedData.Write(ref pos, vendor.Serial);
|
|
||||||
|
|
||||||
#if NO_LOCAL_INIT
|
|
||||||
expectedData.Write(ref pos, (byte)-);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AssertThat.Equal(data, expectedData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using Server.Items;
|
||||||
|
|
||||||
|
namespace Server.Network
|
||||||
|
{
|
||||||
|
public sealed class VendorBuyContent : Packet
|
||||||
|
{
|
||||||
|
public VendorBuyContent(List<BuyItemState> list, bool containerGridLines) : base(0x3C)
|
||||||
|
{
|
||||||
|
EnsureCapacity(list.Count * 19 + 5);
|
||||||
|
|
||||||
|
Stream.Write((short)list.Count);
|
||||||
|
|
||||||
|
for (var i = list.Count - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
var bis = list[i];
|
||||||
|
|
||||||
|
Stream.Write(bis.MySerial);
|
||||||
|
Stream.Write((ushort)bis.ItemID);
|
||||||
|
Stream.Write((byte)0); // itemID offset
|
||||||
|
Stream.Write((ushort)bis.Amount);
|
||||||
|
Stream.Write((short)(i + 1)); // x
|
||||||
|
Stream.Write((short)1); // y
|
||||||
|
if (containerGridLines)
|
||||||
|
{
|
||||||
|
Stream.Write((byte)0); // Grid Location?
|
||||||
|
}
|
||||||
|
Stream.Write(bis.ContainerSerial);
|
||||||
|
Stream.Write((ushort)bis.Hue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class DisplayBuyList : Packet
|
||||||
|
{
|
||||||
|
public DisplayBuyList(Serial vendor, bool highSeas) : base(0x24, highSeas ? 9 : 7)
|
||||||
|
{
|
||||||
|
Stream.Write(vendor);
|
||||||
|
Stream.Write((short)0x30); // buy window id?
|
||||||
|
if (highSeas)
|
||||||
|
{
|
||||||
|
Stream.Write((short)0x00);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class VendorBuyList : Packet
|
||||||
|
{
|
||||||
|
public VendorBuyList(Mobile vendor, List<BuyItemState> list) : base(0x74)
|
||||||
|
{
|
||||||
|
EnsureCapacity(256);
|
||||||
|
|
||||||
|
Stream.Write(!(vendor.FindItemOnLayer(Layer.ShopBuy) is Container buyPack) ? Serial.MinusOne : buyPack.Serial);
|
||||||
|
|
||||||
|
Stream.Write((byte)list.Count);
|
||||||
|
|
||||||
|
for (var i = 0; i < list.Count; ++i)
|
||||||
|
{
|
||||||
|
var bis = list[i];
|
||||||
|
|
||||||
|
Stream.Write(bis.Price);
|
||||||
|
|
||||||
|
var desc = bis.Description ?? "";
|
||||||
|
|
||||||
|
Stream.Write((byte)desc.Length);
|
||||||
|
Stream.WriteAsciiFixed(desc, desc.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class EndVendorBuy : Packet
|
||||||
|
{
|
||||||
|
public EndVendorBuy(Serial vendor) : base(0x3B, 8)
|
||||||
|
{
|
||||||
|
Stream.Write((ushort)8); // length
|
||||||
|
Stream.Write(vendor);
|
||||||
|
Stream.Write((byte)0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -63,7 +63,7 @@ namespace Server.Tests.Network
|
||||||
var vendor = new Mobile(0x1);
|
var vendor = new Mobile(0x1);
|
||||||
vendor.DefaultMobileInit();
|
vendor.DefaultMobileInit();
|
||||||
|
|
||||||
var data = new EndVendorBuy(vendor).Compile();
|
var data = new EndVendorBuy(vendor.Serial).Compile();
|
||||||
|
|
||||||
Span<byte> expectedData = stackalloc byte[8];
|
Span<byte> expectedData = stackalloc byte[8];
|
||||||
var pos = 0;
|
var pos = 0;
|
||||||
|
|
|
||||||
|
|
@ -28,20 +28,15 @@ namespace Server.Network
|
||||||
public static void VendorBuyReply(NetState state, CircularBufferReader reader)
|
public static void VendorBuyReply(NetState state, CircularBufferReader reader)
|
||||||
{
|
{
|
||||||
var vendor = World.FindMobile(reader.ReadUInt32());
|
var vendor = World.FindMobile(reader.ReadUInt32());
|
||||||
var flag = reader.ReadByte();
|
|
||||||
|
|
||||||
if (vendor == null)
|
if (vendor == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vendor.Deleted || !Utility.RangeCheck(vendor.Location, state.Mobile.Location, 10))
|
var flag = reader.ReadByte();
|
||||||
{
|
|
||||||
state.Send(new EndVendorBuy(vendor));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flag == 0x02)
|
if (!vendor.Deleted && Utility.RangeCheck(vendor.Location, state.Mobile.Location, 10) && flag == 0x02)
|
||||||
{
|
{
|
||||||
var msgSize = reader.Remaining;
|
var msgSize = reader.Remaining;
|
||||||
|
|
||||||
|
|
@ -61,15 +56,13 @@ namespace Server.Network
|
||||||
msgSize -= 7;
|
msgSize -= 7;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (buyList.Count > 0 && vendor is IVendor v && v.OnBuyItems(state.Mobile, buyList))
|
if (buyList.Count <= 0 || (vendor as IVendor)?.OnBuyItems(state.Mobile, buyList) != true)
|
||||||
{
|
{
|
||||||
state.Send(new EndVendorBuy(vendor));
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
state.SendEndVendorBuy(vendor.Serial);
|
||||||
state.Send(new EndVendorBuy(vendor));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void VendorSellReply(NetState state, CircularBufferReader reader)
|
public static void VendorSellReply(NetState state, CircularBufferReader reader)
|
||||||
|
|
|
||||||
125
Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs
Normal file
125
Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
/*************************************************************************
|
||||||
|
* ModernUO *
|
||||||
|
* Copyright 2019-2020 - ModernUO Development Team *
|
||||||
|
* Email: hi@modernuo.com *
|
||||||
|
* File: OutgoingVendorBuyPackets.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 <http://www.gnu.org/licenses/>. *
|
||||||
|
*************************************************************************/
|
||||||
|
|
||||||
|
using System.Buffers;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using Server.Items;
|
||||||
|
|
||||||
|
namespace Server.Network
|
||||||
|
{
|
||||||
|
public static class OutgoingVendorBuyPackets
|
||||||
|
{
|
||||||
|
public static void SendVendorBuyContent(this NetState ns, List<BuyItemState> list)
|
||||||
|
{
|
||||||
|
if (ns == null || !ns.GetSendBuffer(out var buffer))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = new CircularBufferWriter(buffer);
|
||||||
|
writer.Write((byte)0x3C); // Packet ID
|
||||||
|
writer.Seek(2, SeekOrigin.Current);
|
||||||
|
|
||||||
|
writer.Write((short)list.Count);
|
||||||
|
|
||||||
|
for (var i = list.Count - 1; i >= 0; --i)
|
||||||
|
{
|
||||||
|
var bis = list[i];
|
||||||
|
|
||||||
|
writer.Write(bis.MySerial);
|
||||||
|
writer.Write((ushort)bis.ItemID);
|
||||||
|
writer.Write((byte)0); // itemID offset
|
||||||
|
writer.Write((ushort)bis.Amount);
|
||||||
|
writer.Write((short)(i + 1)); // x
|
||||||
|
writer.Write((short)1); // y
|
||||||
|
if (ns.ContainerGridLines)
|
||||||
|
{
|
||||||
|
writer.Write((byte)0); // Grid Location?
|
||||||
|
}
|
||||||
|
writer.Write(bis.ContainerSerial);
|
||||||
|
writer.Write((ushort)bis.Hue);
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePacketLength();
|
||||||
|
ns.Send(ref buffer, writer.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SendDisplayBuyList(this NetState ns, Serial vendor)
|
||||||
|
{
|
||||||
|
if (ns == null || !ns.GetSendBuffer(out var buffer))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = new CircularBufferWriter(buffer);
|
||||||
|
writer.Write((byte)0x24); // Packet ID
|
||||||
|
writer.Write(vendor);
|
||||||
|
writer.Write((short)0x30); // Vendor Buy Window
|
||||||
|
if (ns.HighSeas)
|
||||||
|
{
|
||||||
|
writer.Write((short)0x0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ns.Send(ref buffer, writer.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SendVendorBuyList(this NetState ns, Mobile vendor, List<BuyItemState> list)
|
||||||
|
{
|
||||||
|
if (ns == null || !ns.GetSendBuffer(out var buffer))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = new CircularBufferWriter(buffer);
|
||||||
|
writer.Write((byte)0x74); // Packet ID
|
||||||
|
writer.Seek(2, SeekOrigin.Current);
|
||||||
|
writer.Write((vendor.FindItemOnLayer(Layer.ShopBuy) as Container)?.Serial ?? Serial.MinusOne);
|
||||||
|
writer.Write((byte)list.Count);
|
||||||
|
|
||||||
|
for (var i = 0; i < list.Count; ++i)
|
||||||
|
{
|
||||||
|
var bis = list[i];
|
||||||
|
|
||||||
|
writer.Write(bis.Price);
|
||||||
|
|
||||||
|
var desc = bis.Description ?? "";
|
||||||
|
|
||||||
|
writer.Write((byte)desc.Length);
|
||||||
|
writer.WriteAscii(desc); // Doesn't look like it is used anymore
|
||||||
|
}
|
||||||
|
|
||||||
|
writer.WritePacketLength();
|
||||||
|
|
||||||
|
ns.Send(ref buffer, writer.Position);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void SendEndVendorBuy(this NetState ns, Serial vendor)
|
||||||
|
{
|
||||||
|
if (ns == null || !ns.GetSendBuffer(out var buffer))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var writer = new CircularBufferWriter(buffer);
|
||||||
|
writer.Write((byte)0x3B); // Packet ID
|
||||||
|
writer.Write((ushort)8);
|
||||||
|
writer.Write(vendor);
|
||||||
|
writer.Write((byte)0); // Buy count
|
||||||
|
|
||||||
|
ns.Send(ref buffer, writer.Position);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,123 +0,0 @@
|
||||||
/*************************************************************************
|
|
||||||
* ModernUO *
|
|
||||||
* Copyright 2019-2020 - ModernUO Development Team *
|
|
||||||
* Email: hi@modernuo.com *
|
|
||||||
* File: VendorBuyPackets.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 <http://www.gnu.org/licenses/>. *
|
|
||||||
*************************************************************************/
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Server.Items;
|
|
||||||
|
|
||||||
namespace Server.Network
|
|
||||||
{
|
|
||||||
public sealed class VendorBuyContent : Packet
|
|
||||||
{
|
|
||||||
public VendorBuyContent(List<BuyItemState> list) : base(0x3C)
|
|
||||||
{
|
|
||||||
EnsureCapacity(list.Count * 19 + 5);
|
|
||||||
|
|
||||||
Stream.Write((short)list.Count);
|
|
||||||
|
|
||||||
for (var i = list.Count - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
var bis = list[i];
|
|
||||||
|
|
||||||
Stream.Write(bis.MySerial);
|
|
||||||
Stream.Write((ushort)bis.ItemID);
|
|
||||||
Stream.Write((byte)0); // itemID offset
|
|
||||||
Stream.Write((ushort)bis.Amount);
|
|
||||||
Stream.Write((short)(i + 1)); // x
|
|
||||||
Stream.Write((short)1); // y
|
|
||||||
Stream.Write(bis.ContainerSerial);
|
|
||||||
Stream.Write((ushort)bis.Hue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class VendorBuyContent6017 : Packet
|
|
||||||
{
|
|
||||||
public VendorBuyContent6017(List<BuyItemState> list) : base(0x3C)
|
|
||||||
{
|
|
||||||
EnsureCapacity(list.Count * 20 + 5);
|
|
||||||
|
|
||||||
Stream.Write((short)list.Count);
|
|
||||||
|
|
||||||
for (var i = list.Count - 1; i >= 0; --i)
|
|
||||||
{
|
|
||||||
var bis = list[i];
|
|
||||||
|
|
||||||
Stream.Write(bis.MySerial);
|
|
||||||
Stream.Write((ushort)bis.ItemID);
|
|
||||||
Stream.Write((byte)0); // itemID offset
|
|
||||||
Stream.Write((ushort)bis.Amount);
|
|
||||||
Stream.Write((short)(i + 1)); // x
|
|
||||||
Stream.Write((short)1); // y
|
|
||||||
Stream.Write((byte)0); // Grid Location?
|
|
||||||
Stream.Write(bis.ContainerSerial);
|
|
||||||
Stream.Write((ushort)bis.Hue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class DisplayBuyList : Packet
|
|
||||||
{
|
|
||||||
public DisplayBuyList(Mobile vendor) : base(0x24, 7)
|
|
||||||
{
|
|
||||||
Stream.Write(vendor.Serial);
|
|
||||||
Stream.Write((short)0x30); // buy window id?
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class DisplayBuyListHS : Packet
|
|
||||||
{
|
|
||||||
public DisplayBuyListHS(Mobile vendor) : base(0x24, 9)
|
|
||||||
{
|
|
||||||
Stream.Write(vendor.Serial);
|
|
||||||
Stream.Write((short)0x30); // buy window id?
|
|
||||||
Stream.Write((short)0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class VendorBuyList : Packet
|
|
||||||
{
|
|
||||||
public VendorBuyList(Mobile vendor, List<BuyItemState> list) : base(0x74)
|
|
||||||
{
|
|
||||||
EnsureCapacity(256);
|
|
||||||
|
|
||||||
Stream.Write(!(vendor.FindItemOnLayer(Layer.ShopBuy) is Container buyPack) ? Serial.MinusOne : buyPack.Serial);
|
|
||||||
|
|
||||||
Stream.Write((byte)list.Count);
|
|
||||||
|
|
||||||
for (var i = 0; i < list.Count; ++i)
|
|
||||||
{
|
|
||||||
var bis = list[i];
|
|
||||||
|
|
||||||
Stream.Write(bis.Price);
|
|
||||||
|
|
||||||
var desc = bis.Description ?? "";
|
|
||||||
|
|
||||||
// TODO: Test if this is actually WriteAsciiFixed and the extra null doesn't matter.
|
|
||||||
Stream.Write((byte)(desc.Length + 1));
|
|
||||||
Stream.WriteAsciiNull(desc);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class EndVendorBuy : Packet
|
|
||||||
{
|
|
||||||
public EndVendorBuy(Mobile vendor) : base(0x3B, 8)
|
|
||||||
{
|
|
||||||
Stream.Write((ushort)8); // length
|
|
||||||
Stream.Write(vendor.Serial);
|
|
||||||
Stream.Write((byte)0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -127,7 +127,6 @@ namespace Server.Mobiles
|
||||||
|
|
||||||
UpdateBuyInfo();
|
UpdateBuyInfo();
|
||||||
|
|
||||||
// IBuyItemInfo[] buyInfo = this.GetBuyInfo();
|
|
||||||
var info = GetSellInfo();
|
var info = GetSellInfo();
|
||||||
var totalCost = 0;
|
var totalCost = 0;
|
||||||
var validBuy = new List<BuyItemResponse>(list.Count);
|
var validBuy = new List<BuyItemResponse>(list.Count);
|
||||||
|
|
@ -910,13 +909,9 @@ namespace Server.Mobiles
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
if (disp is Item item)
|
if (disp is IPropertyListObject obj)
|
||||||
{
|
{
|
||||||
opls.Add(item.PropertyList);
|
opls.Add(obj.PropertyList);
|
||||||
}
|
|
||||||
else if (disp is Mobile mobile)
|
|
||||||
{
|
|
||||||
opls.Add(mobile.PropertyList);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -981,25 +976,9 @@ namespace Server.Mobiles
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ns.ContainerGridLines)
|
from.NetState.SendVendorBuyContent(list);
|
||||||
{
|
from.NetState.SendVendorBuyList(this, list);
|
||||||
from.Send(new VendorBuyContent6017(list));
|
from.NetState.SendDisplayBuyList(Serial);
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from.Send(new VendorBuyContent(list));
|
|
||||||
}
|
|
||||||
|
|
||||||
from.Send(new VendorBuyList(this, list));
|
|
||||||
|
|
||||||
if (ns.HighSeas)
|
|
||||||
{
|
|
||||||
from.Send(new DisplayBuyListHS(this));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
from.Send(new DisplayBuyList(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
from.Send(new MobileStatusExtended(from)); // make sure their gold amount is sent
|
from.Send(new MobileStatusExtended(from)); // make sure their gold amount is sent
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -102,41 +102,11 @@ namespace Server.Mobiles
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetNameFor(Item item)
|
public string GetNameFor(Item item) => item.Name ?? item.LabelNumber.ToString();
|
||||||
{
|
|
||||||
if (item.Name != null)
|
|
||||||
{
|
|
||||||
return item.Name;
|
|
||||||
}
|
|
||||||
|
|
||||||
return item.LabelNumber.ToString();
|
public bool IsSellable(Item item) => !item.Nontransferable && IsInList(item.GetType());
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsSellable(Item item)
|
public bool IsResellable(Item item) => !item.Nontransferable && IsInList(item.GetType());
|
||||||
{
|
|
||||||
if (item.Nontransferable)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (item.Hue != 0)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
return IsInList(item.GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsResellable(Item item)
|
|
||||||
{
|
|
||||||
if (item.Nontransferable)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (item.Hue != 0)
|
|
||||||
// return false;
|
|
||||||
|
|
||||||
return IsInList(item.GetType());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Add(Type type, int price)
|
public void Add(Type type, int price)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -36,18 +36,8 @@ namespace Server.Mobiles
|
||||||
|
|
||||||
public int Price { get; }
|
public int Price { get; }
|
||||||
|
|
||||||
public string FormattedPrice
|
public string FormattedPrice =>
|
||||||
{
|
Core.ML ? Price.ToString("N0", CultureInfo.GetCultureInfo("en-US")) : Price.ToString();
|
||||||
get
|
|
||||||
{
|
|
||||||
if (Core.ML)
|
|
||||||
{
|
|
||||||
return Price.ToString("N0", CultureInfo.GetCultureInfo("en-US"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return Price.ToString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Description
|
public string Description
|
||||||
{
|
{
|
||||||
|
|
@ -1473,27 +1463,13 @@ namespace Server.Mobiles
|
||||||
string firstWord;
|
string firstWord;
|
||||||
|
|
||||||
var sep = text.IndexOfAny(new[] { ' ', ',' });
|
var sep = text.IndexOfAny(new[] { ' ', ',' });
|
||||||
if (sep >= 0)
|
firstWord = sep >= 0 ? text.Substring(0, sep) : text;
|
||||||
{
|
|
||||||
firstWord = text.Substring(0, sep);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
firstWord = text;
|
|
||||||
}
|
|
||||||
|
|
||||||
string description;
|
string description;
|
||||||
|
|
||||||
if (int.TryParse(firstWord, out var price))
|
if (int.TryParse(firstWord, out var price))
|
||||||
{
|
{
|
||||||
if (sep >= 0)
|
description = sep >= 0 ? text.Substring(sep + 1).Trim() : "";
|
||||||
{
|
|
||||||
description = text.Substring(sep + 1).Trim();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
description = "";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue