Adds more packet tests (#173)

This commit is contained in:
Kamron Batman 2020-07-05 20:14:23 -07:00 committed by GitHub
parent f868c34678
commit 9d4bc7cda2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 1015 additions and 33 deletions

View file

@ -0,0 +1,38 @@
using System;
using Server.Network;
namespace Server.Tests.Network.Packets
{
public static class AttributeNormalizerUtilities
{
public static void Write(int cur, int max, bool normalize, Span<byte> data)
{
if (normalize && AttributeNormalizer.Enabled && max != 0)
{
int maximum = AttributeNormalizer.Maximum;
((ushort)maximum).CopyTo(data.Slice(0, 2));
((ushort)(cur * maximum / max)).CopyTo(data.Slice(2, 2));
return;
}
((ushort)max).CopyTo(data.Slice(0, 2));
((ushort)cur).CopyTo(data.Slice(2, 2));
}
public static void WriteReverse(int cur, int max, bool normalize, Span<byte> data)
{
if (normalize && AttributeNormalizer.Enabled && max != 0)
{
int maximum = AttributeNormalizer.Maximum;
((ushort)(cur * maximum / max)).CopyTo(data.Slice(0, 2));
((ushort)maximum).CopyTo(data.Slice(2, 2));
return;
}
((ushort)cur).CopyTo(data.Slice(0, 2));
((ushort)max).CopyTo(data.Slice(2, 2));
}
}
}

View file

@ -194,7 +194,8 @@ namespace Server.Tests.Network.Packets
RemoteEndPoint = IPEndPoint.Parse("127.0.0.1")
})
{
Account = account
Account = account,
ProtocolChanges = protocolChanges
};
Span<byte> data = new SupportedFeatures(ns).Compile();

View file

@ -5,7 +5,7 @@ using Xunit;
namespace Server.Tests.Network.Packets
{
public class ItemPacketTests
public class ItemPacketTests : IClassFixture<ServerFixture>
{
[Fact]
public void TestWorldItemPacket()
@ -323,7 +323,7 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[5 + 64 * 19]; // Max size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData);
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
pos += 4; // Length + spell count
ushort count = 0;
@ -360,7 +360,7 @@ namespace Server.Tests.Network.Packets
Span<byte> expectedData = stackalloc byte[5 + 64 * 19]; // Max size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData);
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
pos += 4; // Length + spell count
ushort count = 0;
@ -384,5 +384,149 @@ namespace Server.Tests.Network.Packets
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestContainerContentUpdate()
{
Serial serial = 0x1;
Item item = new Item(serial);
Span<byte> data = new ContainerContentUpdate(item).Compile();
Span<byte> expectedData = stackalloc byte[20];
int pos = 0;
((byte)0x25).CopyTo(ref pos, expectedData); // Packet ID
item.Serial.CopyTo(ref pos, expectedData);
((ushort)item.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(item.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)item.X).CopyTo(ref pos, expectedData);
((ushort)item.Y).CopyTo(ref pos, expectedData);
(item.Parent?.Serial ?? Serial.Zero).CopyTo(ref pos, expectedData);
((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)).CopyTo(ref pos, expectedData);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestContainerContentUpdate6017()
{
Serial serial = 0x1;
Item item = new Item(serial);
Span<byte> data = new ContainerContentUpdate6017(item).Compile();
Span<byte> expectedData = stackalloc byte[21];
int pos = 0;
((byte)0x25).CopyTo(ref pos, expectedData); // Packet ID
item.Serial.CopyTo(ref pos, expectedData);
((ushort)item.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(item.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)item.X).CopyTo(ref pos, expectedData);
((ushort)item.Y).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // Grid Location?
(item.Parent?.Serial ?? Serial.Zero).CopyTo(ref pos, expectedData);
((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue)).CopyTo(ref pos, expectedData);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestContainerContent()
{
Container cont = new Container(Serial.LastItem + 1);
cont.AddItem(new Item(Serial.LastItem + 2));
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new ContainerContent(m, cont).Compile();
int count = cont.Items.Count;
Span<byte> expectedData = stackalloc byte[5 + cont.Items.Count * 19]; // Max Size
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
pos += 4; // Length + Count
ushort written = 0;
for (var i = 0; i < count; i++)
{
var child = cont.Items[i];
if (child.Deleted || !m.CanSee(child))
continue;
child.Serial.CopyTo(ref pos, expectedData);
((ushort)child.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(child.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)child.X).CopyTo(ref pos, expectedData);
((ushort)child.Y).CopyTo(ref pos, expectedData);
cont.Serial.CopyTo(ref pos, expectedData);
((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)).CopyTo(ref pos, expectedData);
written++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
written.CopyTo(expectedData.Slice(3, 2));
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestContainerContent6017()
{
Container cont = new Container(Serial.LastItem + 1);
cont.AddItem(new Item(Serial.LastItem + 2));
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new ContainerContent6017(m, cont).Compile();
int count = cont.Items.Count;
Span<byte> expectedData = stackalloc byte[5 + cont.Items.Count * 20];
int pos = 0;
((byte)0x3C).CopyTo(ref pos, expectedData); // Packet ID
pos += 4; // Length + Count
ushort written = 0;
for (var i = 0; i < count; i++)
{
var child = cont.Items[i];
if (child.Deleted || !m.CanSee(child))
continue;
child.Serial.CopyTo(ref pos, expectedData);
((ushort)child.ItemID).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // signed, itemID offset
((ushort)Math.Min(child.Amount, ushort.MaxValue)).CopyTo(ref pos, expectedData);
((ushort)child.X).CopyTo(ref pos, expectedData);
((ushort)child.Y).CopyTo(ref pos, expectedData);
((byte)0).CopyTo(ref pos, expectedData); // Grid Location?
cont.Serial.CopyTo(ref pos, expectedData);
((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue)).CopyTo(ref pos, expectedData);
written++;
}
((ushort)pos).CopyTo(expectedData.Slice(1, 2));
written.CopyTo(expectedData.Slice(3, 2));
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
}
}

View file

@ -0,0 +1,43 @@
using System;
using Server.Network;
using Xunit;
namespace Server.Tests.Network.Packets
{
public class LightPacketTests
{
[Fact]
public void TestGlobalLightLevel()
{
byte lightLevel = 5;
Span<byte> data = new GlobalLightLevel(lightLevel).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x4F, // Packet ID
lightLevel
};
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestPersonalLightLevel()
{
Serial serial = 0x1;
byte lightLevel = 5;
Span<byte> data = new PersonalLightLevel(serial, lightLevel).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x4E, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
lightLevel
};
serial.CopyTo(expectedData.Slice(1, 4));
AssertThat.Equal(data, expectedData);
}
}
}

View file

@ -0,0 +1,198 @@
using System;
using Xunit;
using Server.Network;
namespace Server.Tests.Network.Packets
{
public class MessageTests
{
[Fact]
public void TestMessageLocalized()
{
Serial serial = 0x1;
int graphic = 0x100;
var messageType = MessageType.Label;
int hue = 1024;
int font = 3;
int number = 150000;
string name = "Stuff";
string args = "Arguments";
Span<byte> data = new MessageLocalized(
serial,
graphic,
messageType,
hue,
font,
number,
name,
args
).Compile();
Span<byte> expectedData = stackalloc byte[50 + args.Length * 2];
int pos = 0;
((byte)0xC1).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
number.CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
args.CopyRawUnicodeLittleEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMessageLocalizedAffix()
{
Serial serial = 0x1;
int graphic = 0x100;
var messageType = MessageType.Label;
int hue = 1024;
int font = 3;
int number = 150000;
string name = "Stuff";
string args = "Arguments";
var affixType = AffixType.System;
string affix = "Affix";
Span<byte> data = new MessageLocalizedAffix(
serial,
graphic,
messageType,
hue,
font,
number,
name,
affixType,
affix,
args
).Compile();
Span<byte> expectedData = stackalloc byte[52 + affix.Length + args.Length * 2];
int pos = 0;
((byte)0xCC).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
number.CopyTo(ref pos, expectedData);
((byte)affixType).CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
affix.CopyRawASCIITo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
args.CopyRawUnicodeLittleEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 1); // Terminator
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestAsciiMessage()
{
Serial serial = 0x1;
int graphic = 0x100;
var messageType = MessageType.Label;
int hue = 1024;
int font = 3;
string name = "Stuff";
string text = "Some Text";
Span<byte> data = new AsciiMessage(
serial,
graphic,
messageType,
hue,
font,
name,
text
).Compile();
Span<byte> expectedData = stackalloc byte[45 + text.Length];
int pos = 0;
((byte)0x1C).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
text.CopyRawASCIITo(ref pos, expectedData);
expectedData.Clear(ref pos, 1); // Terminator
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestUnicodeMessage()
{
Serial serial = 0x1;
int graphic = 0x100;
var messageType = MessageType.Label;
int hue = 1024;
int font = 3;
string lang = "ENU";
string name = "Stuff";
string text = "Some Text";
Span<byte> data = new UnicodeMessage(
serial,
graphic,
messageType,
hue,
font,
lang,
name,
text
).Compile();
Span<byte> expectedData = stackalloc byte[50 + text.Length * 2];
int pos = 0;
((byte)0xAE).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
serial.CopyTo(ref pos, expectedData);
((ushort)graphic).CopyTo(ref pos, expectedData);
((byte)messageType).CopyTo(ref pos, expectedData);
((ushort)hue).CopyTo(ref pos, expectedData);
((ushort)font).CopyTo(ref pos, expectedData);
lang.CopyASCIIFixedTo(ref pos, 4, expectedData);
name.CopyASCIIFixedTo(ref pos, 30, expectedData);
text.CopyRawUnicodeBigEndianTo(ref pos, expectedData);
expectedData.Clear(ref pos, 2); // Terminator
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestFollowMessage()
{
Serial serial = 0x1;
Serial serial2 = 0x2;
Span<byte> data = new FollowMessage(serial, serial2).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x15, // Packet ID
0x00, 0x00, 0x00, 0x00, // Follower
0x00, 0x00, 0x00, 0x00, // Followee
};
serial.CopyTo(expectedData.Slice(1, 4));
serial2.CopyTo(expectedData.Slice(5, 4));
AssertThat.Equal(data, expectedData);
}
}
}

View file

@ -0,0 +1,537 @@
using System;
using System.Net;
using Server.Network;
using Xunit;
namespace Server.Tests.Network.Packets
{
public class MobilePacketTests : IClassFixture<ServerFixture>
{
[Fact]
public void TestDeathAnimation()
{
Serial killed = 0x1;
Serial corpse = 0x1000;
Span<byte> data = new DeathAnimation(killed, corpse).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xAF, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial of killed
0x00, 0x00, 0x00, 0x00, // Serial of corpse
0x00, 0x00, 0x00, 0x00
};
killed.CopyTo(expectedData.Slice(1, 4));
corpse.CopyTo(expectedData.Slice(5, 4));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestBondStatus()
{
Serial petSerial = 0x1;
bool bonded = true;
Span<byte> data = new BondedStatus(petSerial, bonded).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xBF, // Packet ID
0x00, 0x0B, // Length
0x00, 0x19, // Sub-packet
0x00, // Sub command
0x00, 0x00, 0x00, 0x00, // Serial
(byte)(bonded ? 0x1 : 0x0)
};
petSerial.CopyTo(expectedData.Slice(6, 4));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileMoving()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
int noto = 10;
Span<byte> data = new MobileMoving(m, noto).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x77, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Body
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, // Z
0x00, // Direction
0x00, 0x00, // Hue
0x00, // Flags
0x00 // Noto
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
((ushort)m.Body).CopyTo(expectedData.Slice(5, 2));
((ushort)m.X).CopyTo(expectedData.Slice(7, 2));
((ushort)m.Y).CopyTo(expectedData.Slice(9, 2));
expectedData[11] = (byte)m.Z;
expectedData[12] = (byte)m.Direction;
((ushort)m.Hue).CopyTo(expectedData.Slice(13, 2));
expectedData[15] = (byte)m.GetPacketFlags();
expectedData[16] = (byte)noto;
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileMovingOld()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
int noto = 10;
Span<byte> data = new MobileMoving(m, noto).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x77, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Body
0x00, 0x00, // X
0x00, 0x00, // Y
0x00, // Z
0x00, // Direction
0x00, 0x00, // Hue
0x00, // Flags
0x00 // Noto
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
((ushort)m.Body).CopyTo(expectedData.Slice(5, 2));
((ushort)m.X).CopyTo(expectedData.Slice(7, 2));
((ushort)m.Y).CopyTo(expectedData.Slice(9, 2));
expectedData[11] = (byte)m.Z;
expectedData[12] = (byte)m.Direction;
((ushort)m.Hue).CopyTo(expectedData.Slice(13, 2));
expectedData[15] = (byte)m.GetOldPacketFlags();
expectedData[16] = (byte)noto;
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileHits()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileHits(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA1, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, false, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileHitsN()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileHitsN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA1, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, true, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileMana()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileMana(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA2, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, false, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileManaN()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileManaN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA2, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, true, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileStam()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileStam(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA3, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, false, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileStamN()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileStamN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0xA3, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00 // Current Hits
};
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, true, expectedData.Slice(5));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileAttributes()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileAttributes(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2D, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00, // Current Hits
0x00, 0x00, // Max Mana
0x00, 0x00, // Current Mana
0x00, 0x00, // Max Stam
0x00, 0x00 // Current Stam
};
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, false, expectedData.Slice(5));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, false, expectedData.Slice(9));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, false, expectedData.Slice(13));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileAttributesN()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
Span<byte> data = new MobileAttributesN(m).Compile();
Span<byte> expectedData = stackalloc byte[]
{
0x2D, // Packet ID
0x00, 0x00, 0x00, 0x00, // Serial
0x00, 0x00, // Max Hits
0x00, 0x00, // Current Hits
0x00, 0x00, // Max Mana
0x00, 0x00, // Current Mana
0x00, 0x00, // Max Stam
0x00, 0x00 // Current Stam
};
int max = AttributeNormalizer.Maximum;
m.Serial.CopyTo(expectedData.Slice(1, 4));
AttributeNormalizerUtilities.Write(m.Hits, m.HitsMax, true, expectedData.Slice(5));
AttributeNormalizerUtilities.Write(m.Mana, m.ManaMax, true, expectedData.Slice(9));
AttributeNormalizerUtilities.Write(m.Stam, m.StamMax, true, expectedData.Slice(13));
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileName()
{
var m = new Mobile(0x1)
{
Name = "Some Really Long Mobile Name That Gets Cut off",
};
m.DefaultMobileInit();
Span<byte> data = new MobileName(m).Compile();
Span<byte> expectedData = stackalloc byte[37];
int pos = 0;
((byte)0x98).CopyTo(ref pos, expectedData);
((ushort)0x25).CopyTo(ref pos, expectedData);
m.Serial.CopyTo(ref pos, expectedData);
(m.Name ?? "").CopyRawASCIITo(ref pos, 29, expectedData);
((byte)0x0).CopyTo(ref pos, expectedData); // Null terminator
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileAnimation()
{
Serial mobile = 0x1;
int action = 200;
int frameCount = 5;
int repeatCount = 1;
bool reverse = false;
bool repeat = false;
byte delay = 5;
Span<byte> data = new MobileAnimation(
mobile,
action,
frameCount,
repeatCount,
!reverse,
repeat,
delay
).Compile();
Span<byte> expectedData = stackalloc byte[14];
int pos = 0;
((byte)0x6E).CopyTo(ref pos, expectedData);
mobile.CopyTo(ref pos, expectedData);
((ushort)action).CopyTo(ref pos, expectedData);
((ushort)frameCount).CopyTo(ref pos, expectedData);
((ushort)repeatCount).CopyTo(ref pos, expectedData);
reverse.CopyTo(ref pos, expectedData);
repeat.CopyTo(ref pos, expectedData);
delay.CopyTo(ref pos, expectedData);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestNewMobileAnimation()
{
Serial mobile = 0x1;
int action = 200;
int frameCount = 5;
byte delay = 5;
Span<byte> data = new NewMobileAnimation(
mobile,
action,
frameCount,
delay
).Compile();
Span<byte> expectedData = stackalloc byte[10];
int pos = 0;
((byte)0xE2).CopyTo(ref pos, expectedData);
mobile.CopyTo(ref pos, expectedData);
((ushort)action).CopyTo(ref pos, expectedData);
((ushort)frameCount).CopyTo(ref pos, expectedData);
delay.CopyTo(ref pos, expectedData);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileStatusCompact()
{
var m = new Mobile(0x1);
m.DefaultMobileInit();
bool canBeRenamed = false;
Span<byte> data = new MobileStatusCompact(canBeRenamed, m).Compile();
Span<byte> expectedData = stackalloc byte[43];
int pos = 0;
((byte)0x11).CopyTo(ref pos, expectedData); // Packet ID
((ushort)expectedData.Length).CopyTo(ref pos, expectedData); // Length
m.Serial.CopyTo(ref pos, expectedData);
(m.Name ?? "").CopyASCIIFixedTo(ref pos, 30, expectedData);
AttributeNormalizerUtilities.WriteReverse(m.Hits, m.HitsMax, true, expectedData.Slice(pos));
pos += 4;
canBeRenamed.CopyTo(ref pos, expectedData);
AssertThat.Equal(data, expectedData);
}
[Fact]
public void TestMobileStatusExtended()
{
var beholder = new Mobile(0x1)
{
Name = "Random Mobile 1"
};
beholder.DefaultMobileInit();
var beheld = new Mobile(0x2)
{
Name = "Random Mobile 2"
};
beheld.DefaultMobileInit();
NetState ns = new NetState(new AccountPacketTests.TestConnectionContext
{
RemoteEndPoint = IPEndPoint.Parse("127.0.0.1")
});
Span<byte> data = new MobileStatus(beholder, beheld, ns).Compile();
Span<byte> expectedData = stackalloc byte[121]; // Max Size
int pos = 0;
((byte)0x11).CopyTo(ref pos, expectedData);
pos += 2; // Length
int type;
bool notSelf = beholder != beheld;
if (notSelf) type = 0;
else if (Core.HS && ns.ExtendedStatus) type = 6;
else if (Core.ML && ns.SupportsExpansion(Expansion.ML)) type = 5;
else type = Core.AOS ? 4 : 3;
beheld.Serial.CopyTo(ref pos, expectedData);
beheld.Name.CopyASCIIFixedTo(ref pos, 30, expectedData);
AttributeNormalizerUtilities.WriteReverse(beheld.Hits, beheld.HitsMax, notSelf, expectedData.Slice(pos));
pos += 4;
beheld.CanBeRenamedBy(beheld).CopyTo(ref pos, expectedData);
((byte)type).CopyTo(ref pos, expectedData);
if (type > 0)
{
beheld.Female.CopyTo(ref pos, expectedData);
((ushort)beheld.Str).CopyTo(ref pos, expectedData);
((ushort)beheld.Dex).CopyTo(ref pos, expectedData);
((ushort)beheld.Int).CopyTo(ref pos, expectedData);
AttributeNormalizerUtilities.WriteReverse(beheld.Stam, beheld.StamMax, notSelf, expectedData.Slice(pos));
pos += 4;
AttributeNormalizerUtilities.WriteReverse(beheld.Mana, beheld.ManaMax, notSelf, expectedData.Slice(pos));
pos += 4;
beheld.TotalGold.CopyTo(ref pos, expectedData);
((ushort)(Core.AOS ? beheld.PhysicalResistance : (int)(beheld.ArmorRating + 0.5))).CopyTo(ref pos, expectedData);
((ushort)(Mobile.BodyWeight + beheld.TotalWeight)).CopyTo(ref pos, expectedData);
if (type >= 5)
{
((ushort)beheld.MaxWeight).CopyTo(ref pos, expectedData);
((byte)(beheld.Race.RaceID + 1)).CopyTo(ref pos, expectedData); // 0x00 for a non-ML enabled account
}
((ushort)beheld.StatCap).CopyTo(ref pos, expectedData);
((byte)beheld.Followers).CopyTo(ref pos, expectedData);
((byte)beheld.FollowersMax).CopyTo(ref pos, expectedData);
if (type >= 4)
{
((ushort)beheld.FireResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.ColdResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.PoisonResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.EnergyResistance).CopyTo(ref pos, expectedData);
((ushort)beheld.Luck).CopyTo(ref pos, expectedData);
}
int min = 0;
int max = 0;
beheld.Weapon?.GetStatusDamage(beheld, out min, out max);
((ushort)min).CopyTo(ref pos, expectedData);
((ushort)max).CopyTo(ref pos, expectedData);
beheld.TithingPoints.CopyTo(ref pos, expectedData);
if (type >= 6)
for (var i = 0; i < 15; ++i)
((ushort)beheld.GetAOSStatus(i)).CopyTo(ref pos, expectedData);
}
((ushort)pos).CopyTo(expectedData.Slice(1)); // Length
expectedData = expectedData.Slice(0, pos);
AssertThat.Equal(data, expectedData);
}
}
}

View file

@ -119,7 +119,7 @@ namespace Server.Tests.Network.Packets
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawASCIITo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos));
pos += Encoding.ASCII.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -133,7 +133,7 @@ namespace Server.Tests.Network.Packets
public static void CopyASCIITo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length);
pos += 2 + Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos + 2));
pos += 2 + Encoding.ASCII.GetBytes(str, bytes.Slice(pos + 2));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
@ -148,7 +148,7 @@ namespace Server.Tests.Network.Packets
public static void CopyASCIINullTo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)(str.Length + 1));
pos += 3 + Encoding.ASCII.GetBytes(str.AsSpan(), bytes.Slice(pos + 2));
pos += 3 + Encoding.ASCII.GetBytes(str, bytes.Slice(pos + 2));
bytes[pos - 1] = 0; // null terminator
}
@ -211,7 +211,19 @@ namespace Server.Tests.Network.Packets
public static void CopyUnicodeBigEndianTo(this string str, ref int pos, Span<byte> bytes)
{
BinaryPrimitives.WriteUInt16BigEndian(bytes.Slice(pos, 2), (ushort)str.Length);
pos += 2 + Encoding.BigEndianUnicode.GetBytes(str.AsSpan(), bytes.Slice(pos + 2));
pos += 2 + Encoding.BigEndianUnicode.GetBytes(str, bytes.Slice(pos + 2));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawUnicodeBigEndianTo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.BigEndianUnicode.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void CopyRawUnicodeLittleEndianTo(this string str, ref int pos, Span<byte> bytes)
{
pos += Encoding.Unicode.GetBytes(str, bytes.Slice(pos));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]

View file

@ -630,7 +630,7 @@ namespace Server.Network
{
var info = ExpansionInfo.Table[i];
if ((info.RequiredClient != null && Version >= info.RequiredClient) || (Flags & info.ClientFlags) != 0)
if (info.RequiredClient != null && Version >= info.RequiredClient || (Flags & info.ClientFlags) != 0)
return info;
}
@ -642,13 +642,10 @@ namespace Server.Network
public ProtocolChanges ProtocolChanges { get; set; }
public bool SupportsExpansion(ExpansionInfo info, bool checkCoreExpansion = true)
{
if (info == null || (checkCoreExpansion && (int)Core.Expansion < info.ID))
return false;
return info.RequiredClient != null ? Version >= info.RequiredClient : (Flags & info.ClientFlags) != 0;
}
public bool SupportsExpansion(ExpansionInfo info, bool checkCoreExpansion = true) =>
info != null && (!checkCoreExpansion || (int)Core.Expansion >= info.ID) && (info.RequiredClient != null
? Version >= info.RequiredClient
: (Flags & info.ClientFlags) != 0);
public bool SupportsExpansion(Expansion ex, bool checkCoreExpansion = true) =>
SupportsExpansion(ExpansionInfo.GetInfo(ex), checkCoreExpansion);

View file

@ -68,7 +68,6 @@ namespace Server.Network
}
}
// Pre-7.0.0.0 Mobile Moving
public sealed class MobileMovingOld : Packet
{
public MobileMovingOld(Mobile m, int noto) : base(0x77, 17)
@ -178,7 +177,6 @@ namespace Server.Network
}
}
// unsure of proper format, client crashes
public sealed class MobileName : Packet
{
public MobileName(Mobile m) : base(0x98)
@ -186,7 +184,8 @@ namespace Server.Network
EnsureCapacity(37);
Stream.Write(m.Serial);
Stream.WriteAsciiFixed(m.Name ?? "", 30);
Stream.WriteAsciiFixed(m.Name ?? "", 29);
Stream.Write((byte)0); // Null terminator
}
}

View file

@ -12,12 +12,13 @@ namespace Server.Items
private bool m_Editable;
[Constructible]
public MapItem() : base(0x14EC)
public MapItem(Map facet = null) : base(0x14EC)
{
Weight = 1.0;
Width = 200;
Height = 200;
Facet = facet;
}
public MapItem(Serial serial) : base(serial)
@ -36,6 +37,9 @@ namespace Server.Items
[CommandProperty(AccessLevel.GameMaster)]
public int Height { get; set; }
[CommandProperty(AccessLevel.GameMaster)]
public Map Facet { get; set; }
public List<Point2D> Pins { get; } = new List<Point2D>();
public int OnCraft(int quality, bool makersMark, Mobile from, CraftSystem craftSystem, Type typeRes, BaseTool tool,
@ -79,7 +83,18 @@ namespace Server.Items
public virtual void DisplayTo(Mobile from)
{
from.Send(new MapDetails(this));
NetState ns = from.NetState;
if (ns.NewCharacterList) // 7.0.13.0+ supports maps on all facets
from.Send(new MapDetailsNew(this));
else if (Facet != null && Facet != Map.Felucca && Facet != Map.Trammel) // Is it Felucca and Trammel, or just Felucca?
{
from.SendMessage("You must have client 7.0.13.0 or higher to display this map.");
return;
}
else
from.Send(new MapDetails(this));
from.Send(new MapDisplay(this));
for (int i = 0; i < Pins.Count; ++i)
@ -318,23 +333,21 @@ namespace Server.Items
}
}
/*
private sealed class MapDetailsNew : Packet
{
public MapDetailsNew( MapItem map ) : base ( 0xF5, 21 )
public MapDetailsNew(MapItem map) : base(0xF5, 21)
{
m_Stream.Write( (int) map.Serial );
m_Stream.Write( (short) 0x139D );
m_Stream.Write( (short) map.Bounds.Start.X );
m_Stream.Write( (short) map.Bounds.Start.Y );
m_Stream.Write( (short) map.Bounds.End.X );
m_Stream.Write( (short) map.Bounds.End.Y );
m_Stream.Write( (short) map.Width );
m_Stream.Write( (short) map.Height );
m_Stream.Write( (short) ( map.Facet == null ? 0 : map.Facet.MapID ) );
Stream.Write(map.Serial);
Stream.Write((short)0x139D);
Stream.Write((short)map.Bounds.Start.X);
Stream.Write((short)map.Bounds.Start.Y);
Stream.Write((short)map.Bounds.End.X);
Stream.Write((short)map.Bounds.End.Y);
Stream.Write((short)map.Width);
Stream.Write((short)map.Height);
Stream.Write((short)(map.Facet?.MapID ?? 0));
}
}
*/
private abstract class MapCommand : Packet
{