fix: Exempts localhost from IPLimiter. Preps testing for io_uring (#2316)

### Summary
* Exempts localhost from IPLimiter
* Updates tests to have proper sequential testing with packets
* Updates tests to clean up NetState
This commit is contained in:
Kamron Batman 2026-01-20 08:54:15 -08:00 • committed by GitHub
parent 8133983b64
commit 1e4c32c809
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
77 changed files with 4612 additions and 4616 deletions

View file

@ -1,4 +1,4 @@
namespace Server.Tests;
namespace Server.Tests.Maps;
public static class TestMapDefinitions
{

View file

@ -2,6 +2,7 @@ using System.IO;
using System.Reflection;
using System.Threading;
using Server.Items;
using Server.Tests.Maps;
namespace Server.Tests;

View file

@ -2,7 +2,7 @@ using System;
using Server.Buffers;
using Xunit;
namespace Server.Tests.Tests.Buffers;
namespace Server.Tests.Buffers;
[Collection("Sequential Server Tests")]
public class STArrayPoolTests

View file

@ -3,7 +3,7 @@ using System.Buffers;
using System.IO;
using Xunit;
namespace Server.Tests;
namespace Server.Tests.Buffers;
public class SpanReaderTests
{

View file

@ -3,7 +3,7 @@ using System.Buffers;
using System.IO;
using Xunit;
namespace Server.Tests;
namespace Server.Tests.Buffers;
public class SpanWriterTests
{

View file

@ -1,7 +1,7 @@
using Server.Items;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
/// <summary>
/// Tests for CanFitItem which allows Surface+Impassable tiles (tables, furniture) as valid surfaces.
@ -9,13 +9,6 @@ namespace Server.Tests.Tests.Maps;
[Collection("Sequential Server Tests")]
public class CanFitItemTests
{
private readonly ServerFixture _fixture;
public CanFitItemTests(ServerFixture fixture)
{
_fixture = fixture;
}
private void SkipIfNoTileData()
{
Skip.If(!ServerFixture.TileDataLoaded, "TileData not loaded - client files required");

View file

@ -1,6 +1,6 @@
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
/// <summary>
/// Tests for CanSpawnMobile that don't require TileData (client files).

View file

@ -1,7 +1,7 @@
using Server.Items;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
/// <summary>
/// Tests for CanSpawnMobile that require TileData (client files) to be loaded.

View file

@ -5,7 +5,7 @@ using Server.Accounting;
using Server.Network;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class ClientEnumeratorTests

View file

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class ItemByDistanceEnumeratorTests

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Server.Items;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class ItemEnumeratorTests

View file

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class MobileByDistanceEnumeratorTests

View file

@ -2,7 +2,7 @@ using System;
using System.Collections.Generic;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class MobileEnumeratorTests

View file

@ -3,7 +3,7 @@ using System.Collections.Generic;
using Server.Items;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class MultiEnumeratorTests

View file

@ -2,7 +2,7 @@ using System.Collections.Generic;
using Server.Items;
using Xunit;
namespace Server.Tests.Tests.Maps;
namespace Server.Tests.Maps;
[Collection("Sequential Server Tests")]
public class StaticTileEnumeratorTests

View file

@ -89,7 +89,7 @@ public class AccountPacketTests
// var account = new MockAccount(new[] { firstMobile, null, secondMobile });
var expected = new ChangeCharacter(account).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChangeCharacter(account);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -101,7 +101,7 @@ public class AccountPacketTests
{
var expected = new ClientVersionReq().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendClientVersionRequest();
@ -114,7 +114,7 @@ public class AccountPacketTests
{
var expected = new DeleteResult(DeleteResultType.BadRequest).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCharacterDeleteResult(DeleteResultType.BadRequest);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -126,7 +126,7 @@ public class AccountPacketTests
{
var expected = new PopupMessage(PMMessage.LoginSyncError).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPopupMessage(PMMessage.LoginSyncError);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -149,7 +149,7 @@ public class AccountPacketTests
[4] = null
};
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.Account = account;
ns.ProtocolChanges = protocolChanges;
@ -174,7 +174,7 @@ public class AccountPacketTests
var expected = new LoginConfirm(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLoginConfirmation(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -186,7 +186,7 @@ public class AccountPacketTests
{
var expected = new LoginComplete().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLoginComplete();
var result = ns.SendPipe.Reader.AvailableToRead();
@ -211,7 +211,7 @@ public class AccountPacketTests
var expected = new CharacterListUpdate(account).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCharacterListUpdate(account);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -241,7 +241,7 @@ public class AccountPacketTests
var expected = new CharacterList(account, info).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.CityInfo = info;
ns.Account = account;
ns.ProtocolChanges = ProtocolChanges.Version70130;
@ -275,7 +275,7 @@ public class AccountPacketTests
var expected = new CharacterListOld(account, info).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.CityInfo = info;
ns.Account = account;
@ -291,7 +291,7 @@ public class AccountPacketTests
var reason = ALRReason.BadComm;
var expected = new AccountLoginRej(reason).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendAccountLoginRejected(reason);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -308,7 +308,7 @@ public class AccountPacketTests
var expected = new AccountLoginAck(info).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ServerInfo = info;
ns.SendAccountLoginAck();
@ -325,7 +325,7 @@ public class AccountPacketTests
var expected = new PlayServerAck(si, authId).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPlayServerAck(si, authId);

View file

@ -2,361 +2,360 @@ using System;
using Server.Accounting;
using Server.Network;
namespace Server.Tests.Network
namespace Server.Tests.Network;
public sealed class ChangeCharacter : Packet
{
public sealed class ChangeCharacter : Packet
public ChangeCharacter(IAccount a) : base(0x81)
{
public ChangeCharacter(IAccount a) : base(0x81)
EnsureCapacity(305);
var count = 0;
for (var i = 0; i < a.Length; ++i)
{
EnsureCapacity(305);
var count = 0;
for (var i = 0; i < a.Length; ++i)
if (a[i] != null)
{
if (a[i] != null)
{
++count;
}
}
Stream.Write((byte)count);
Stream.Write((byte)0);
for (var i = 0; i < a.Length; ++i)
{
var m = a[i];
if (a[i] != null)
{
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
++count;
}
}
}
public sealed class ClientVersionReq : Packet
{
public ClientVersionReq() : base(0xBD)
Stream.Write((byte)count);
Stream.Write((byte)0);
for (var i = 0; i < a.Length; ++i)
{
EnsureCapacity(3);
}
}
public sealed class DeleteResult : Packet
{
public DeleteResult(DeleteResultType res) : base(0x85, 2)
{
Stream.Write((byte)res);
}
}
public sealed class PopupMessage : Packet
{
public PopupMessage(PMMessage msg) : base(0x53, 2)
{
Stream.Write((byte)msg);
}
}
public sealed class SupportedFeatures : Packet
{
public SupportedFeatures(NetState ns) : base(0xB9, ns.ExtendedSupportedFeatures ? 5 : 3)
{
var flags = ExpansionInfo.CoreExpansion.SupportedFeatures;
if (ns.Account.Limit >= 6)
var m = a[i];
if (a[i] != null)
{
flags |= FeatureFlags.LiveAccount;
flags &= ~FeatureFlags.UOTD;
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
if (ns.Account.Limit > 6)
{
flags |= FeatureFlags.SeventhCharacterSlot;
}
else
{
flags |= FeatureFlags.SixthCharacterSlot;
}
}
if (ns.ExtendedSupportedFeatures)
{
Stream.Write((uint)flags);
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Write((ushort)flags);
Stream.Fill(60);
}
}
}
public sealed class LoginConfirm : Packet
{
public LoginConfirm(Mobile m) : base(0x1B, 37)
{
Stream.Write(m.Serial);
Stream.Write(0);
Stream.Write((short)m.Body);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((short)m.Z);
Stream.Write((byte)m.Direction);
Stream.Write((byte)0);
Stream.Write(-1);
var map = m.Map;
if (map == null || map == Map.Internal)
{
map = m.LogoutMap;
}
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)(map?.Width ?? Map.Felucca.Width));
Stream.Write((short)(map?.Height ?? Map.Felucca.Height));
Stream.Fill();
}
}
public sealed class LoginComplete : Packet
{
public LoginComplete() : base(0x55, 1)
{
}
}
public sealed class CharacterListUpdate : Packet
{
public CharacterListUpdate(IAccount a) : base(0x86)
{
EnsureCapacity(4 + a.Length * 60);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
}
public sealed class CharacterList : Packet
{
public CharacterList(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(11 + a.Length * 60 + info.Length * 89);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 32);
Stream.WriteAsciiFixed(ci.Building, 32);
Stream.Write(ci.X);
Stream.Write(ci.Y);
Stream.Write(ci.Z);
Stream.Write(ci.Map.MapID);
Stream.Write(ci.Description);
Stream.Write(0);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
{
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
}
else if (count == 6)
{
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
}
else if (a.Limit == 1)
{
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
}
Stream.Write((int)flags); // Additional Flags
Stream.Write((short)-1);
}
}
public sealed class CharacterListOld : Packet
{
public CharacterListOld(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(9 + a.Length * 60 + info.Length * 63);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 31);
Stream.WriteAsciiFixed(ci.Building, 31);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
{
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
}
else if (count == 6)
{
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
}
else if (a.Limit == 1)
{
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
}
Stream.Write((int)flags); // Additional Flags
}
}
public sealed class AccountLoginRej : Packet
{
public AccountLoginRej(ALRReason reason) : base(0x82, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class AccountLoginAck : Packet
{
public AccountLoginAck(ServerInfo[] info) : base(0xA8)
{
EnsureCapacity(6 + info.Length * 40);
Stream.Write((byte)0x5D); // Unknown
Stream.Write((ushort)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var si = info[i];
Stream.Write((ushort)i);
Stream.WriteAsciiFixed(si.Name, 32);
Stream.Write((byte)si.FullPercent);
Stream.Write((sbyte)si.TimeZone);
// UO Doesn't support IPv6
Stream.Write(si.RawAddress);
}
}
}
public sealed class PlayServerAck : Packet
{
public PlayServerAck(ServerInfo si, int authId) : base(0x8C, 11)
{
var addr = si.RawAddress;
Stream.Write((byte)addr);
Stream.Write((byte)(addr >> 8));
Stream.Write((byte)(addr >> 16));
Stream.Write((byte)(addr >> 24));
Stream.Write((short)si.Address.Port);
Stream.Write(authId);
}
}
}
public sealed class ClientVersionReq : Packet
{
public ClientVersionReq() : base(0xBD)
{
EnsureCapacity(3);
}
}
public sealed class DeleteResult : Packet
{
public DeleteResult(DeleteResultType res) : base(0x85, 2)
{
Stream.Write((byte)res);
}
}
public sealed class PopupMessage : Packet
{
public PopupMessage(PMMessage msg) : base(0x53, 2)
{
Stream.Write((byte)msg);
}
}
public sealed class SupportedFeatures : Packet
{
public SupportedFeatures(NetState ns) : base(0xB9, ns.ExtendedSupportedFeatures ? 5 : 3)
{
var flags = ExpansionInfo.CoreExpansion.SupportedFeatures;
if (ns.Account.Limit >= 6)
{
flags |= FeatureFlags.LiveAccount;
flags &= ~FeatureFlags.UOTD;
if (ns.Account.Limit > 6)
{
flags |= FeatureFlags.SeventhCharacterSlot;
}
else
{
flags |= FeatureFlags.SixthCharacterSlot;
}
}
if (ns.ExtendedSupportedFeatures)
{
Stream.Write((uint)flags);
}
else
{
Stream.Write((ushort)flags);
}
}
}
public sealed class LoginConfirm : Packet
{
public LoginConfirm(Mobile m) : base(0x1B, 37)
{
Stream.Write(m.Serial);
Stream.Write(0);
Stream.Write((short)m.Body);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((short)m.Z);
Stream.Write((byte)m.Direction);
Stream.Write((byte)0);
Stream.Write(-1);
var map = m.Map;
if (map == null || map == Map.Internal)
{
map = m.LogoutMap;
}
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)(map?.Width ?? Map.Felucca.Width));
Stream.Write((short)(map?.Height ?? Map.Felucca.Height));
Stream.Fill();
}
}
public sealed class LoginComplete : Packet
{
public LoginComplete() : base(0x55, 1)
{
}
}
public sealed class CharacterListUpdate : Packet
{
public CharacterListUpdate(IAccount a) : base(0x86)
{
EnsureCapacity(4 + a.Length * 60);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
}
}
public sealed class CharacterList : Packet
{
public CharacterList(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(11 + a.Length * 60 + info.Length * 89);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
if (a[i] != null)
{
Stream.WriteAsciiFixed(a[i].Name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 32);
Stream.WriteAsciiFixed(ci.Building, 32);
Stream.Write(ci.X);
Stream.Write(ci.Y);
Stream.Write(ci.Z);
Stream.Write(ci.Map.MapID);
Stream.Write(ci.Description);
Stream.Write(0);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
{
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
}
else if (count == 6)
{
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
}
else if (a.Limit == 1)
{
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
}
Stream.Write((int)flags); // Additional Flags
Stream.Write((short)-1);
}
}
public sealed class CharacterListOld : Packet
{
public CharacterListOld(IAccount a, CityInfo[] info) : base(0xA9)
{
EnsureCapacity(9 + a.Length * 60 + info.Length * 63);
var highSlot = -1;
for (var i = 0; i < a.Length; ++i)
{
if (a[i] != null)
{
highSlot = i;
}
}
var count = Math.Max(Math.Max(highSlot + 1, a.Limit), 5);
Stream.Write((byte)count);
for (var i = 0; i < count; ++i)
{
var m = a[i];
if (m != null)
{
var name = (m.RawName?.Trim()).DefaultIfNullOrEmpty("-no name-");
Stream.WriteAsciiFixed(name, 30);
Stream.Fill(30); // password
}
else
{
Stream.Fill(60);
}
}
Stream.Write((byte)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var ci = info[i];
Stream.Write((byte)i);
Stream.WriteAsciiFixed(ci.City, 31);
Stream.WriteAsciiFixed(ci.Building, 31);
}
var flags = ExpansionInfo.CoreExpansion.CharacterListFlags;
if (count > 6)
{
flags |= CharacterListFlags.SeventhCharacterSlot |
CharacterListFlags.SixthCharacterSlot; // 7th Character Slot - TODO: Is SixthCharacterSlot Required?
}
else if (count == 6)
{
flags |= CharacterListFlags.SixthCharacterSlot; // 6th Character Slot
}
else if (a.Limit == 1)
{
flags |= CharacterListFlags.SlotLimit &
CharacterListFlags.OneCharacterSlot; // Limit Characters & One Character
}
Stream.Write((int)flags); // Additional Flags
}
}
public sealed class AccountLoginRej : Packet
{
public AccountLoginRej(ALRReason reason) : base(0x82, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class AccountLoginAck : Packet
{
public AccountLoginAck(ServerInfo[] info) : base(0xA8)
{
EnsureCapacity(6 + info.Length * 40);
Stream.Write((byte)0x5D); // Unknown
Stream.Write((ushort)info.Length);
for (var i = 0; i < info.Length; ++i)
{
var si = info[i];
Stream.Write((ushort)i);
Stream.WriteAsciiFixed(si.Name, 32);
Stream.Write((byte)si.FullPercent);
Stream.Write((sbyte)si.TimeZone);
// UO Doesn't support IPv6
Stream.Write(si.RawAddress);
}
}
}
public sealed class PlayServerAck : Packet
{
public PlayServerAck(ServerInfo si, int authId) : base(0x8C, 11)
{
var addr = si.RawAddress;
Stream.Write((byte)addr);
Stream.Write((byte)(addr >> 8));
Stream.Write((byte)(addr >> 16));
Stream.Write((byte)(addr >> 24));
Stream.Write((short)si.Address.Port);
Stream.Write(authId);
}
}

View file

@ -1,37 +1,36 @@
namespace Server.Network
namespace Server.Network;
public static class AttributeNormalizer
{
public static class AttributeNormalizer
public static int Maximum { get; set; } = 100;
public static bool Enabled { get; set; } = true;
public static void Write(PacketWriter stream, int cur, int max)
{
public static int Maximum { get; set; } = 100;
public static bool Enabled { get; set; } = true;
public static void Write(PacketWriter stream, int cur, int max)
if (Enabled && max != 0)
{
if (Enabled && max != 0)
{
stream.Write((short)Maximum);
stream.Write((short)(cur * Maximum / max));
}
else
{
stream.Write((short)max);
stream.Write((short)cur);
}
stream.Write((short)Maximum);
stream.Write((short)(cur * Maximum / max));
}
public static void WriteReverse(PacketWriter stream, int cur, int max)
else
{
if (Enabled && max != 0)
{
stream.Write((short)(cur * Maximum / max));
stream.Write((short)Maximum);
}
else
{
stream.Write((short)cur);
stream.Write((short)max);
}
stream.Write((short)max);
stream.Write((short)cur);
}
}
}
public static void WriteReverse(PacketWriter stream, int cur, int max)
{
if (Enabled && max != 0)
{
stream.Write((short)(cur * Maximum / max));
stream.Write((short)Maximum);
}
else
{
stream.Write((short)cur);
stream.Write((short)max);
}
}
}

View file

@ -1,49 +1,49 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class CombatPacketTests
{
public class CombatPacketTests
[Fact]
public void TestSwing()
{
[Fact]
public void TestSwing()
{
var attacker = (Serial)0x1024;
var defender = (Serial)0x2048;
var attacker = (Serial)0x1024;
var defender = (Serial)0x2048;
var expected = new Swing(attacker, defender).Compile();
var expected = new Swing(attacker, defender).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSwing(attacker, defender);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSwing(attacker, defender);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory, InlineData(true), InlineData(false)]
public void TestSetWarMode(bool warmode)
{
var expected = new SetWarMode(warmode).Compile();
[Theory, InlineData(true), InlineData(false)]
public void TestSetWarMode(bool warmode)
{
var expected = new SetWarMode(warmode).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSetWarMode(warmode);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSetWarMode(warmode);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestChangeCombatant()
{
var serial = (Serial)0x1024;
[Fact]
public void TestChangeCombatant()
{
var serial = (Serial)0x1024;
var expected = new ChangeCombatant(serial).Compile();
var expected = new ChangeCombatant(serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChangeCombatant(serial);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChangeCombatant(serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,31 +1,30 @@
namespace Server.Network
namespace Server.Network;
public sealed class Swing : Packet
{
public sealed class Swing : Packet
public Swing(Serial attacker, Serial defender) : base(0x2F, 10)
{
public Swing(Serial attacker, Serial defender) : base(0x2F, 10)
{
Stream.Write((byte)0);
Stream.Write(attacker);
Stream.Write(defender);
}
}
public sealed class SetWarMode : Packet
{
public SetWarMode(bool mode) : base(0x72, 5)
{
Stream.Write(mode);
Stream.Write((byte)0x00);
Stream.Write((byte)0x32);
Stream.Write((byte)0x00);
}
}
public sealed class ChangeCombatant : Packet
{
public ChangeCombatant(Serial combatant) : base(0xAA, 5)
{
Stream.Write(combatant);
}
Stream.Write((byte)0);
Stream.Write(attacker);
Stream.Write(defender);
}
}
public sealed class SetWarMode : Packet
{
public SetWarMode(bool mode) : base(0x72, 5)
{
Stream.Write(mode);
Stream.Write((byte)0x00);
Stream.Write((byte)0x32);
Stream.Write((byte)0x00);
}
}
public sealed class ChangeCombatant : Packet
{
public ChangeCombatant(Serial combatant) : base(0xAA, 5)
{
Stream.Write(combatant);
}
}

View file

@ -2,200 +2,199 @@ using Server.Items;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class ContainerPacketTests
{
[Collection("Sequential Server Tests")]
public class ContainerPacketTests
[Fact]
public void TestContainerDisplay()
{
var serial = (Serial)0x1024;
ushort gumpId = 100;
[Fact]
public void TestContainerDisplay()
{
var serial = (Serial)0x1024;
ushort gumpId = 100;
var expected = new ContainerDisplay(serial, gumpId).Compile();
var expected = new ContainerDisplay(serial, gumpId).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayContainer(serial, gumpId);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayContainer(serial, gumpId);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestContainerDisplayHS()
{
var serial = (Serial)0x1024;
ushort gumpId = 100;
[Fact]
public void TestContainerDisplayHS()
{
var serial = (Serial)0x1024;
ushort gumpId = 100;
var expected = new ContainerDisplayHS(serial, gumpId).Compile();
var expected = new ContainerDisplayHS(serial, gumpId).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
ns.SendDisplayContainer(serial, gumpId);
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
ns.SendDisplayContainer(serial, gumpId);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestDisplaySpellbook()
{
var serial = (Serial)0x1024;
[Fact]
public void TestDisplaySpellbook()
{
var serial = (Serial)0x1024;
var expected = new DisplaySpellbook(serial).Compile();
var expected = new DisplaySpellbook(serial).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplaySpellbook(serial);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplaySpellbook(serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestDisplaySpellbookHS()
{
var serial = (Serial)0x1024;
[Fact]
public void TestDisplaySpellbookHS()
{
var serial = (Serial)0x1024;
var expected = new DisplaySpellbookHS(serial).Compile();
var expected = new DisplaySpellbookHS(serial).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
ns.SendDisplaySpellbook(serial);
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.HighSeas;
ns.SendDisplaySpellbook(serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestNewSpellbookContent()
{
var serial = (Serial)0x1024;
ushort graphic = 100;
ushort offset = 10;
ulong content = 0x123456789ABCDEF0;
var opl = ObjectPropertyList.Enabled;
[Fact]
public void TestNewSpellbookContent()
{
var serial = (Serial)0x1024;
ushort graphic = 100;
ushort offset = 10;
ulong content = 0x123456789ABCDEF0;
var opl = ObjectPropertyList.Enabled;
var expected = new NewSpellbookContent(serial, graphic, offset, content).Compile();
var expected = new NewSpellbookContent(serial, graphic, offset, content).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.NewSpellbook;
ObjectPropertyList.Enabled = true;
ns.SendSpellbookContent(serial, graphic, offset, content);
ObjectPropertyList.Enabled = opl;
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ns.ProtocolChanges | ProtocolChanges.ContainerGridLines | ProtocolChanges.NewSpellbook;
ObjectPropertyList.Enabled = true;
ns.SendSpellbookContent(serial, graphic, offset, content);
ObjectPropertyList.Enabled = opl;
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestSpellbookContent()
{
var serial = (Serial)0x1024;
ushort offset = 10;
ushort graphic = 100;
ulong content = 0x123456789ABCDEF0;
[Fact]
public void TestSpellbookContent()
{
var serial = (Serial)0x1024;
ushort offset = 10;
ushort graphic = 100;
ulong content = 0x123456789ABCDEF0;
var expected = new SpellbookContent(serial, offset, content).Compile();
var expected = new SpellbookContent(serial, offset, content).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSpellbookContent(serial, graphic, offset, content);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSpellbookContent(serial, graphic, offset, content);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestSpellbookContent6017()
{
var serial = (Serial)0x1024;
ushort offset = 10;
ushort graphic = 100;
ulong content = 0x123456789ABCDEF0;
[Fact]
public void TestSpellbookContent6017()
{
var serial = (Serial)0x1024;
ushort offset = 10;
ushort graphic = 100;
ulong content = 0x123456789ABCDEF0;
var expected = new SpellbookContent6017(serial, offset, content).Compile();
var expected = new SpellbookContent6017(serial, offset, content).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendSpellbookContent(serial, graphic, offset, content);
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendSpellbookContent(serial, graphic, offset, content);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestContainerContentUpdate()
{
var serial = (Serial)0x1024;
var item = new Item(serial);
[Fact]
public void TestContainerContentUpdate()
{
var serial = (Serial)0x1024;
var item = new Item(serial);
var expected = new ContainerContentUpdate(item).Compile();
var expected = new ContainerContentUpdate(item).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendContainerContentUpdate(item);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendContainerContentUpdate(item);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestContainerContentUpdate6017()
{
var serial = (Serial)0x1024;
var item = new Item(serial);
[Fact]
public void TestContainerContentUpdate6017()
{
var serial = (Serial)0x1024;
var item = new Item(serial);
var expected = new ContainerContentUpdate6017(item).Compile();
var expected = new ContainerContentUpdate6017(item).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendContainerContentUpdate(item);
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendContainerContentUpdate(item);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestContainerContent()
{
var cont = new Container(World.NewItem);
cont.AddItem(new Item(World.NewItem));
cont.Map = Map.Felucca;
[Fact]
public void TestContainerContent()
{
var cont = new Container(World.NewItem);
cont.AddItem(new Item(World.NewItem));
cont.Map = Map.Felucca;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.AccessLevel = AccessLevel.Administrator;
m.Map = Map.Felucca;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.AccessLevel = AccessLevel.Administrator;
m.Map = Map.Felucca;
var expected = new ContainerContent(m, cont).Compile();
var expected = new ContainerContent(m, cont).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendContainerContent(m, cont);
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendContainerContent(m, cont);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestContainerContent6017()
{
var cont = new Container(World.NewItem);
cont.AddItem(new Item(World.NewItem));
cont.Map = Map.Felucca;
[Fact]
public void TestContainerContent6017()
{
var cont = new Container(World.NewItem);
cont.AddItem(new Item(World.NewItem));
cont.Map = Map.Felucca;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.AccessLevel = AccessLevel.Administrator;
m.Map = Map.Felucca;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.AccessLevel = AccessLevel.Administrator;
m.Map = Map.Felucca;
var expected = new ContainerContent6017(m, cont).Compile();
var expected = new ContainerContent6017(m, cont).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendContainerContent(m, cont);
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendContainerContent(m, cont);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,270 +1,269 @@
using System;
using System.IO;
namespace Server.Network
namespace Server.Network;
public sealed class DisplaySpellbook : Packet
{
public sealed class DisplaySpellbook : Packet
public DisplaySpellbook(Serial book) : base(0x24, 7)
{
public DisplaySpellbook(Serial book) : base(0x24, 7)
{
Stream.Write(book);
Stream.Write((short)-1);
}
Stream.Write(book);
Stream.Write((short)-1);
}
}
public sealed class DisplaySpellbookHS : Packet
public sealed class DisplaySpellbookHS : Packet
{
public DisplaySpellbookHS(Serial book) : base(0x24, 9)
{
public DisplaySpellbookHS(Serial book) : base(0x24, 9)
{
Stream.Write(book);
Stream.Write((short)-1);
Stream.Write((short)0x7D);
}
Stream.Write(book);
Stream.Write((short)-1);
Stream.Write((short)0x7D);
}
}
public sealed class NewSpellbookContent : Packet
public sealed class NewSpellbookContent : Packet
{
public NewSpellbookContent(Serial spellbook, int graphic, int offset, ulong content) : base(0xBF)
{
public NewSpellbookContent(Serial spellbook, int graphic, int offset, ulong content) : base(0xBF)
EnsureCapacity(23);
Stream.Write((short)0x1B);
Stream.Write((short)0x01);
Stream.Write(spellbook);
Stream.Write((short)graphic);
Stream.Write((short)offset);
for (var i = 0; i < 8; ++i)
{
EnsureCapacity(23);
Stream.Write((short)0x1B);
Stream.Write((short)0x01);
Stream.Write(spellbook);
Stream.Write((short)graphic);
Stream.Write((short)offset);
for (var i = 0; i < 8; ++i)
{
Stream.Write((byte)(content >> (i * 8)));
}
}
}
public sealed class SpellbookContent : Packet
{
public SpellbookContent(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 19);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
{
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class SpellbookContent6017 : Packet
{
public SpellbookContent6017(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 20);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
{
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((byte)0); // Grid Location?
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerDisplay : Packet
{
public ContainerDisplay(Serial cont, int gumpId) : base(0x24, 7)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
}
}
public sealed class ContainerDisplayHS : Packet
{
public ContainerDisplayHS(Serial cont, int gumpId) : base(0x24, 9)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
Stream.Write((short)0x7D);
}
}
public sealed class ContainerContentUpdate : Packet
{
public ContainerContentUpdate(Item item) : base(0x25, 20)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContentUpdate6017 : Packet
{
public ContainerContentUpdate6017(Item item) : base(0x25, 21)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContent : Packet
{
public ContainerContent(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 19);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerContent6017 : Packet
{
public ContainerContent6017(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 20);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
Stream.Write((byte)(content >> (i * 8)));
}
}
}
public sealed class SpellbookContent : Packet
{
public SpellbookContent(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 19);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
{
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class SpellbookContent6017 : Packet
{
public SpellbookContent6017(Serial spellbook, int offset, ulong content) : base(0x3C)
{
EnsureCapacity(5 + 64 * 20);
var written = 0;
Stream.Write((ushort)0);
ulong mask = 1;
for (var i = 0; i < 64; ++i, mask <<= 1)
{
if ((content & mask) != 0)
{
Stream.Write(0x7FFFFFFF - i);
Stream.Write((ushort)0);
Stream.Write((byte)0);
Stream.Write((ushort)(i + offset));
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((byte)0); // Grid Location?
Stream.Write(spellbook);
Stream.Write((short)0);
++written;
}
}
Stream.Seek(3, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerDisplay : Packet
{
public ContainerDisplay(Serial cont, int gumpId) : base(0x24, 7)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
}
}
public sealed class ContainerDisplayHS : Packet
{
public ContainerDisplayHS(Serial cont, int gumpId) : base(0x24, 9)
{
Stream.Write(cont);
Stream.Write((short)gumpId);
Stream.Write((short)0x7D);
}
}
public sealed class ContainerContentUpdate : Packet
{
public ContainerContentUpdate(Item item) : base(0x25, 20)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContentUpdate6017 : Packet
{
public ContainerContentUpdate6017(Item item) : base(0x25, 21)
{
Serial parentSerial;
if (item.Parent is Item parentItem)
{
parentSerial = parentItem.Serial;
}
else
{
Console.WriteLine("Warning: ContainerContentUpdate on item with !(parent is Item)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((ushort)item.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(item.Amount, ushort.MaxValue));
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(parentSerial);
Stream.Write((ushort)(item.QuestItem ? Item.QuestItemHue : item.Hue));
}
}
public sealed class ContainerContent : Packet
{
public ContainerContent(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 19);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}
public sealed class ContainerContent6017 : Packet
{
public ContainerContent6017(Mobile beholder, Item beheld) : base(0x3C)
{
var items = beheld.Items;
var count = items.Count;
EnsureCapacity(5 + count * 20);
var pos = Stream.Position;
var written = 0;
Stream.Write((ushort)0);
for (var i = 0; i < count; ++i)
{
var child = items[i];
if (!child.Deleted && beholder.CanSee(child))
{
var loc = child.Location;
Stream.Write(child.Serial);
Stream.Write((ushort)child.ItemID);
Stream.Write((byte)0); // signed, itemID offset
Stream.Write((ushort)Math.Min(child.Amount, ushort.MaxValue));
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(beheld.Serial);
Stream.Write((ushort)(child.QuestItem ? Item.QuestItemHue : child.Hue));
++written;
}
}
Stream.Seek(pos, SeekOrigin.Begin);
Stream.Write((ushort)written);
}
}

View file

@ -1,39 +1,38 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class DamagePacketTests
{
[Theory, InlineData(10), InlineData(-5), InlineData(1024)]
public void TestDamagePacketOld(int inputAmount)
{
[Theory, InlineData(10), InlineData(-5), InlineData(1024)]
public void TestDamagePacketOld(int inputAmount)
{
var serial = (Serial)0x1024;
var serial = (Serial)0x1024;
var expected = new DamagePacketOld(serial, inputAmount).Compile();
var expected = new DamagePacketOld(serial, inputAmount).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDamage(serial, inputAmount);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDamage(serial, inputAmount);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory, InlineData(10), InlineData(-5), InlineData(1024), InlineData(100000)]
public void TestDamage(int inputAmount)
{
var serial = (Serial)0x1024;
[Theory, InlineData(10), InlineData(-5), InlineData(1024), InlineData(100000)]
public void TestDamage(int inputAmount)
{
var serial = (Serial)0x1024;
var expected = new DamagePacket(serial, inputAmount).Compile();
var expected = new DamagePacket(serial, inputAmount).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.DamagePacket;
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.DamagePacket;
ns.SendDamage(serial, inputAmount);
ns.SendDamage(serial, inputAmount);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,28 +1,27 @@
using System;
namespace Server.Network
namespace Server.Network;
public sealed class DamagePacketOld : Packet
{
public sealed class DamagePacketOld : Packet
public DamagePacketOld(Serial mobile, int amount) : base(0xBF)
{
public DamagePacketOld(Serial mobile, int amount) : base(0xBF)
{
EnsureCapacity(11);
EnsureCapacity(11);
Stream.Write((short)0x22);
Stream.Write((byte)1);
Stream.Write(mobile);
Stream.Write((short)0x22);
Stream.Write((byte)1);
Stream.Write(mobile);
Stream.Write((byte)Math.Clamp(amount, 0, 255));
}
}
public sealed class DamagePacket : Packet
{
public DamagePacket(Serial mobile, int amount) : base(0x0B, 7)
{
Stream.Write(mobile);
Stream.Write((ushort)Math.Clamp(amount, 0, 0xFFFF));
}
Stream.Write((byte)Math.Clamp(amount, 0, 255));
}
}
public sealed class DamagePacket : Packet
{
public DamagePacket(Serial mobile, int amount) : base(0x0B, 7)
{
Stream.Write(mobile);
Stream.Write((ushort)Math.Clamp(amount, 0, 0xFFFF));
}
}

View file

@ -2,117 +2,117 @@ using System;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class EffectPackets
{
public class EffectPackets
[Theory, InlineData(10, 1000, 10, 5)]
public void TestSoundEffect(ushort soundID, int x, int y, int z)
{
[Theory, InlineData(10, 1000, 10, 5)]
public void TestSoundEffect(ushort soundID, int x, int y, int z)
{
var p = new Point3D(x, y, z);
var p = new Point3D(x, y, z);
var expected = new PlaySound(soundID, p).Compile();
var expected = new PlaySound(soundID, p).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSoundEffect(soundID, p);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSoundEffect(soundID, p);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestParticleEffect()
{
var effectType = EffectType.Moving;
var serial = (Serial)0x4000;
var from = (Serial)0x1000;
var to = (Serial)0x2000;
var itemId = 0x100;
var fromPoint = new Point3D(1000, 100, -10);
var toPoint = new Point3D(1500, 500, 0);
byte speed = 3;
byte duration = 2;
var direction = false;
var explode = false;
var hue = 0x1024;
var renderMode = 1;
ushort effect = 3;
ushort explodeEffect = 0;
ushort explodeSound = 0;
byte layer = 9;
ushort unknown = 0;
[Fact]
public void TestParticleEffect()
{
var effectType = EffectType.Moving;
var serial = (Serial)0x4000;
var from = (Serial)0x1000;
var to = (Serial)0x2000;
var itemId = 0x100;
var fromPoint = new Point3D(1000, 100, -10);
var toPoint = new Point3D(1500, 500, 0);
byte speed = 3;
byte duration = 2;
var direction = false;
var explode = false;
var hue = 0x1024;
var renderMode = 1;
ushort effect = 3;
ushort explodeEffect = 0;
ushort explodeSound = 0;
byte layer = 9;
ushort unknown = 0;
var expected = new ParticleEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
).Compile();
var expected = new ParticleEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
).Compile();
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateParticleEffect(
actual,
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
);
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.ParticleEffectLength];
OutgoingEffectPackets.CreateParticleEffect(
actual,
effectType, from, to, itemId, fromPoint, toPoint, speed, duration, direction,
explode, hue, renderMode, effect, explodeEffect, explodeSound, serial, layer,
unknown
);
AssertThat.Equal(actual, expected);
}
AssertThat.Equal(actual, expected);
}
[Fact]
public void TestHuedEffect()
{
var effectType = EffectType.Moving;
var from = (Serial)0x1000;
var to = (Serial)0x2000;
var itemId = 0x100;
var fromPoint = new Point3D(1000, 100, -10);
var toPoint = new Point3D(1500, 500, 0);
byte speed = 3;
byte duration = 2;
var direction = false;
var explode = false;
var hue = 0x1024;
var renderMode = 1;
[Fact]
public void TestHuedEffect()
{
var effectType = EffectType.Moving;
var from = (Serial)0x1000;
var to = (Serial)0x2000;
var itemId = 0x100;
var fromPoint = new Point3D(1000, 100, -10);
var toPoint = new Point3D(1500, 500, 0);
byte speed = 3;
byte duration = 2;
var direction = false;
var explode = false;
var hue = 0x1024;
var renderMode = 1;
var expected = new HuedEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
).Compile();
var expected = new HuedEffect(
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
).Compile();
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateHuedEffect(
actual,
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
);
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.HuedEffectLength];
OutgoingEffectPackets.CreateHuedEffect(
actual,
effectType, from, to, itemId, fromPoint, toPoint, speed,
duration, direction, explode, hue, renderMode
);
AssertThat.Equal(actual, expected);
}
AssertThat.Equal(actual, expected);
}
[Theory, InlineData(ScreenEffectType.DarkFlash), InlineData(ScreenEffectType.FadeInOut)]
public void TestScreenEffect(ScreenEffectType screenType)
{
var expected = new ScreenEffect(screenType).Compile();
[Theory, InlineData(ScreenEffectType.DarkFlash), InlineData(ScreenEffectType.FadeInOut)]
public void TestScreenEffect(ScreenEffectType screenType)
{
var expected = new ScreenEffect(screenType).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendScreenEffect(screenType);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendScreenEffect(screenType);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestBoltEffect()
{
IEntity entity = new Entity((Serial)0x1000, new Point3D(1000, 100, -10), Map.Felucca);
var hue = 0x1024;
var expected = new BoltEffect(entity, hue).Compile();
[Fact]
public void TestBoltEffect()
{
IEntity entity = new Entity((Serial)0x1000, new Point3D(1000, 100, -10), Map.Felucca);
var hue = 0x1024;
var expected = new BoltEffect(entity, hue).Compile();
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect(actual, entity, hue);
Span<byte> actual = stackalloc byte[OutgoingEffectPackets.BoltEffectLength];
OutgoingEffectPackets.CreateBoltEffect(actual, entity, hue);
AssertThat.Equal(actual, expected);
}
AssertThat.Equal(actual, expected);
}
}

View file

@ -1,265 +1,264 @@
namespace Server.Network
namespace Server.Network;
public sealed class PlaySound : Packet
{
public sealed class PlaySound : Packet
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
public PlaySound(int soundID, IPoint3D target) : base(0x54, 12)
{
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public class ParticleEffect : Packet
{
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
}
public class HuedEffect : Packet
{
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
}
public sealed class TargetParticleEffect : ParticleEffect
{
public TargetParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int layer, int unknown
) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
layer,
unknown
)
{
}
}
public sealed class TargetEffect : HuedEffect
{
public TargetEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class LocationParticleEffect : ParticleEffect
{
public LocationParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int unknown
) : base(
EffectType.FixedXYZ,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
255,
unknown
)
{
}
}
public sealed class LocationEffect : HuedEffect
{
public LocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedXYZ,
Serial.Zero,
Serial.Zero,
itemID,
p,
p,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class MovingParticleEffect : ParticleEffect
{
public MovingParticleEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
Serial.Zero,
(int)layer,
unknown
)
{
}
}
public sealed class MovingEffect : HuedEffect
{
public MovingEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
)
{
}
}
public class ScreenEffect : Packet
{
public ScreenEffect(ScreenEffectType type)
: base(0x70, 28)
{
Stream.Write((byte)0x04);
Stream.Fill(8);
Stream.Write((short)type);
Stream.Fill(16);
}
}
public sealed class BoltEffect : Packet
{
public BoltEffect(IEntity target, int hue) : base(0xC0, 36)
{
Stream.Write((byte)0x01); // type
Stream.Write(target.Serial);
Stream.Write(Serial.Zero);
Stream.Write((short)0); // itemID
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((byte)0); // speed
Stream.Write((byte)0); // duration
Stream.Write((short)0); // unk
Stream.Write(false); // fixed direction
Stream.Write(false); // explode
Stream.Write(hue);
Stream.Write(0); // render mode
}
Stream.Write((byte)1); // flags
Stream.Write((short)soundID);
Stream.Write((short)0); // volume
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((short)target.Z);
}
}
public class ParticleEffect : Packet
{
public ParticleEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode, int effect,
int explodeEffect, int explodeSound, Serial serial, int layer, int unknown
) : base(0xC7, 49)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
Stream.Write((short)effect);
Stream.Write((short)explodeEffect);
Stream.Write((short)explodeSound);
Stream.Write(serial);
Stream.Write((byte)layer);
Stream.Write((short)unknown);
}
}
public class HuedEffect : Packet
{
public HuedEffect(
EffectType type, Serial from, Serial to, int itemID, IPoint3D fromPoint, IPoint3D toPoint,
int speed, int duration, bool fixedDirection, bool explode, int hue, int renderMode
) : base(0xC0, 36)
{
Stream.Write((byte)type);
Stream.Write(from);
Stream.Write(to);
Stream.Write((short)itemID);
Stream.Write((short)fromPoint.X);
Stream.Write((short)fromPoint.Y);
Stream.Write((sbyte)fromPoint.Z);
Stream.Write((short)toPoint.X);
Stream.Write((short)toPoint.Y);
Stream.Write((sbyte)toPoint.Z);
Stream.Write((byte)speed);
Stream.Write((byte)duration);
Stream.Write((byte)0);
Stream.Write((byte)0);
Stream.Write(fixedDirection);
Stream.Write(explode);
Stream.Write(hue);
Stream.Write(renderMode);
}
}
public sealed class TargetParticleEffect : ParticleEffect
{
public TargetParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int layer, int unknown
) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
layer,
unknown
)
{
}
}
public sealed class TargetEffect : HuedEffect
{
public TargetEffect(IEntity e, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedFrom,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class LocationParticleEffect : ParticleEffect
{
public LocationParticleEffect(
IEntity e, int itemID, int speed, int duration, int hue, int renderMode, int effect,
int unknown
) : base(
EffectType.FixedXYZ,
e.Serial,
Serial.Zero,
itemID,
e.Location,
e.Location,
speed,
duration,
true,
false,
hue,
renderMode,
effect,
1,
0,
e.Serial,
255,
unknown
)
{
}
}
public sealed class LocationEffect : HuedEffect
{
public LocationEffect(IPoint3D p, int itemID, int speed, int duration, int hue, int renderMode) : base(
EffectType.FixedXYZ,
Serial.Zero,
Serial.Zero,
itemID,
p,
p,
speed,
duration,
true,
false,
hue,
renderMode
)
{
}
}
public sealed class MovingParticleEffect : ParticleEffect
{
public MovingParticleEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode, int effect, int explodeEffect, int explodeSound, EffectLayer layer,
int unknown
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode,
effect,
explodeEffect,
explodeSound,
Serial.Zero,
(int)layer,
unknown
)
{
}
}
public sealed class MovingEffect : HuedEffect
{
public MovingEffect(
IEntity from, IEntity to, int itemID, int speed, int duration, bool fixedDirection,
bool explodes, int hue, int renderMode
) : base(
EffectType.Moving,
from.Serial,
to.Serial,
itemID,
from.Location,
to.Location,
speed,
duration,
fixedDirection,
explodes,
hue,
renderMode
)
{
}
}
public class ScreenEffect : Packet
{
public ScreenEffect(ScreenEffectType type)
: base(0x70, 28)
{
Stream.Write((byte)0x04);
Stream.Fill(8);
Stream.Write((short)type);
Stream.Fill(16);
}
}
public sealed class BoltEffect : Packet
{
public BoltEffect(IEntity target, int hue) : base(0xC0, 36)
{
Stream.Write((byte)0x01); // type
Stream.Write(target.Serial);
Stream.Write(Serial.Zero);
Stream.Write((short)0); // itemID
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((short)target.X);
Stream.Write((short)target.Y);
Stream.Write((sbyte)target.Z);
Stream.Write((byte)0); // speed
Stream.Write((byte)0); // duration
Stream.Write((short)0); // unk
Stream.Write(false); // fixed direction
Stream.Write(false); // explode
Stream.Write(hue);
Stream.Write(0); // render mode
}
}

View file

@ -2,65 +2,64 @@ using System.Collections.Generic;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class EquipmentPacketTests
{
[Theory]
[InlineData(null, false)]
[InlineData("Some Crafter", false)]
[InlineData("", true)]
public void TestDisplayEquipmentInfo(string name, bool unidentified)
{
[Theory]
[InlineData(null, false)]
[InlineData("Some Crafter", false)]
[InlineData("", true)]
public void TestDisplayEquipmentInfo(string name, bool unidentified)
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.RawName = name;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.RawName = name;
var item = new Item(World.NewItem);
var item = new Item(World.NewItem);
var info = new EquipmentInfo(
500000,
m,
unidentified,
new[]
{
new EquipInfoAttribute(500001, 1),
new EquipInfoAttribute(500002, 2),
new EquipInfoAttribute(500002, 3)
}
);
var info = new EquipmentInfo(
500000,
m,
unidentified,
new[]
{
new EquipInfoAttribute(500001, 1),
new EquipInfoAttribute(500002, 2),
new EquipInfoAttribute(500002, 3)
}
);
var expected = new DisplayEquipmentInfo(item, info).Compile();
var expected = new DisplayEquipmentInfo(item, info).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayEquipmentInfo(
item.Serial,
info.Number,
info.Crafter?.RawName,
info.Unidentified,
new List<EquipInfoAttribute>(info.Attributes)
);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayEquipmentInfo(
item.Serial,
info.Number,
info.Crafter?.RawName,
info.Unidentified,
new List<EquipInfoAttribute>(info.Attributes)
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestEquipUpdate()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
[Fact]
public void TestEquipUpdate()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var item = new Item(World.NewItem) { Parent = m };
var item = new Item(World.NewItem) { Parent = m };
var expected = new EquipUpdate(item).Compile();
var expected = new EquipUpdate(item).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEquipUpdate(item);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEquipUpdate(item);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,98 +1,97 @@
using System;
namespace Server.Network
namespace Server.Network;
public class EquipmentInfo
{
public class EquipmentInfo
public EquipmentInfo(int number, Mobile crafter, bool unidentified, EquipInfoAttribute[] attributes)
{
public EquipmentInfo(int number, Mobile crafter, bool unidentified, EquipInfoAttribute[] attributes)
{
Number = number;
Crafter = crafter;
Unidentified = unidentified;
Attributes = attributes;
}
public int Number { get; }
public Mobile Crafter { get; }
public bool Unidentified { get; }
public EquipInfoAttribute[] Attributes { get; }
Number = number;
Crafter = crafter;
Unidentified = unidentified;
Attributes = attributes;
}
public sealed class DisplayEquipmentInfo : Packet
public int Number { get; }
public Mobile Crafter { get; }
public bool Unidentified { get; }
public EquipInfoAttribute[] Attributes { get; }
}
public sealed class DisplayEquipmentInfo : Packet
{
public DisplayEquipmentInfo(Item item, EquipmentInfo info) : base(0xBF)
{
public DisplayEquipmentInfo(Item item, EquipmentInfo info) : base(0xBF)
var attrs = info.Attributes;
EnsureCapacity(
17 + (info.Crafter?.RawName?.Length ?? 0) +
(info.Unidentified ? 4 : 0) + attrs.Length * 6
);
Stream.Write((short)0x10);
Stream.Write(item.Serial);
Stream.Write(info.Number);
var name = info.Crafter?.RawName?.Trim() ?? "";
if (name.Length > 0)
{
var attrs = info.Attributes;
Stream.Write(-3);
EnsureCapacity(
17 + (info.Crafter?.RawName?.Length ?? 0) +
(info.Unidentified ? 4 : 0) + attrs.Length * 6
);
Stream.Write((short)0x10);
Stream.Write(item.Serial);
Stream.Write(info.Number);
var name = info.Crafter?.RawName?.Trim() ?? "";
if (name.Length > 0)
{
Stream.Write(-3);
var length = name.Length;
Stream.Write((ushort)length);
Stream.WriteAsciiFixed(name, length);
}
if (info.Unidentified)
{
Stream.Write(-4);
}
for (var i = 0; i < attrs.Length; ++i)
{
Stream.Write(attrs[i].Number);
Stream.Write((short)attrs[i].Charges);
}
Stream.Write(-1);
var length = name.Length;
Stream.Write((ushort)length);
Stream.WriteAsciiFixed(name, length);
}
}
public sealed class EquipUpdate : Packet
{
public EquipUpdate(Item item) : base(0x2E, 15)
if (info.Unidentified)
{
Serial parentSerial;
var parent = item.Parent as Mobile;
var hue = item.Hue;
if (parent != null)
{
parentSerial = parent.Serial;
if (parent.SolidHueOverride >= 0)
{
hue = parent.SolidHueOverride;
}
}
else
{
Console.WriteLine("Warning: EquipUpdate on item with !(parent is Mobile)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((byte)item.Layer);
Stream.Write(parentSerial);
Stream.Write((short)hue);
Stream.Write(-4);
}
for (var i = 0; i < attrs.Length; ++i)
{
Stream.Write(attrs[i].Number);
Stream.Write((short)attrs[i].Charges);
}
Stream.Write(-1);
}
}
public sealed class EquipUpdate : Packet
{
public EquipUpdate(Item item) : base(0x2E, 15)
{
Serial parentSerial;
var parent = item.Parent as Mobile;
var hue = item.Hue;
if (parent != null)
{
parentSerial = parent.Serial;
if (parent.SolidHueOverride >= 0)
{
hue = parent.SolidHueOverride;
}
}
else
{
Console.WriteLine("Warning: EquipUpdate on item with !(parent is Mobile)");
parentSerial = Serial.Zero;
}
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((byte)item.Layer);
Stream.Write(parentSerial);
Stream.Write((short)hue);
}
}

View file

@ -12,7 +12,7 @@ public class GumpPacketTests
{
var expected = new CloseGump(typeId, buttonId).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCloseGump(typeId, buttonId);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -29,7 +29,7 @@ public class GumpPacketTests
var expected = new DisplaySignGump(gumpSerial, gumpId, unknownString, caption).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplaySignGump(gumpSerial, gumpId, unknownString, caption);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -41,7 +41,7 @@ public class GumpPacketTests
{
var gump = new NameChangeDeedGump();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
var expected = gump.Compile(ns).Compile();
ns.SendGump(gump);
@ -60,7 +60,7 @@ public class GumpPacketTests
var gump = new AdminGump(m, AdminGumpPage.Clients);
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
var expected = gump.Compile(ns).Compile();
ns.SendGump(gump);

View file

@ -6,190 +6,189 @@ using Server.Compression;
using Server.Gumps;
using Server.Network;
namespace Server.Tests
namespace Server.Tests;
public interface IGumpWriter
{
public interface IGumpWriter
int TextEntries { get; set; }
int Switches { get; set; }
void AppendLayout(bool val);
void AppendLayout(int val);
void AppendLayout(uint val);
void AppendLayout(Serial serial);
void AppendLayoutNS(int val);
void AppendLayout(string text);
void AppendLayoutNS(string text);
void AppendLayout(ReadOnlySpan<byte> buffer);
void WriteStrings(List<string> strings);
void Flush();
}
public sealed class CloseGump : Packet
{
public CloseGump(int typeID, int buttonID) : base(0xBF)
{
int TextEntries { get; set; }
int Switches { get; set; }
EnsureCapacity(13);
void AppendLayout(bool val);
void AppendLayout(int val);
void AppendLayout(uint val);
void AppendLayout(Serial serial);
void AppendLayoutNS(int val);
void AppendLayout(string text);
void AppendLayoutNS(string text);
void AppendLayout(ReadOnlySpan<byte> buffer);
void WriteStrings(List<string> strings);
void Flush();
}
public sealed class CloseGump : Packet
{
public CloseGump(int typeID, int buttonID) : base(0xBF)
{
EnsureCapacity(13);
Stream.Write((short)0x04);
Stream.Write(typeID);
Stream.Write(buttonID);
}
}
public sealed class DisplayGumpPacked : Packet, IGumpWriter
{
private static readonly byte[] m_Buffer = new byte[48];
private readonly Gump m_Gump;
private readonly PacketWriter m_Layout;
private readonly PacketWriter m_Strings;
private int m_StringCount;
static DisplayGumpPacked() => m_Buffer[0] = (byte)' ';
public DisplayGumpPacked(Gump gump)
: base(0xDD)
{
m_Gump = gump;
m_Layout = PacketWriter.CreateInstance(8192);
m_Strings = PacketWriter.CreateInstance(8192);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? " 1"u8 : " 0"u8);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(Serial serial) => AppendLayout(serial.Value);
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
m_Layout.Write(m_Buffer, 1, bytes);
}
public void AppendLayoutNS(string text)
{
m_Layout.WriteAsciiFixed(text, text.Length);
}
public void AppendLayout(string text)
{
AppendLayout(" @"u8);
m_Layout.WriteAsciiFixed(text, text.Length);
AppendLayout("@"u8);
}
public void AppendLayout(ReadOnlySpan<byte> buffer)
{
m_Layout.Write(buffer);
}
public void WriteStrings(List<string> strings)
{
m_StringCount = strings.Count;
for (var i = 0; i < strings.Count; ++i)
{
var v = strings[i] ?? "";
m_Strings.Write((ushort)v.Length);
m_Strings.WriteBigUniFixed(v, v.Length);
}
}
public void Flush()
{
EnsureCapacity(28 + (int)m_Layout.Length + (int)m_Strings.Length);
Stream.Write(m_Gump.Serial);
Stream.Write(m_Gump.TypeID);
Stream.Write(m_Gump.X);
Stream.Write(m_Gump.Y);
// Note: layout MUST be null terminated (don't listen to krrios)
m_Layout.Write((byte)0);
WritePacked(m_Layout);
Stream.Write(m_StringCount);
WritePacked(m_Strings);
PacketWriter.ReleaseInstance(m_Layout);
PacketWriter.ReleaseInstance(m_Strings);
}
private void WritePacked(PacketWriter src)
{
var buffer = src.UnderlyingStream.GetBuffer();
var length = (int)src.Length;
if (length == 0)
{
Stream.Write(0);
return;
}
var wantLength = 1 + length * 1024 / 1000;
wantLength += 4095;
wantLength &= ~4095;
var packBuffer = ArrayPool<byte>.Shared.Rent(wantLength);
var bytesPacked = Deflate.Standard.Pack(packBuffer, buffer.AsSpan(0, length));
Stream.Write(4 + bytesPacked);
Stream.Write(length);
Stream.Write(packBuffer, 0, bytesPacked);
ArrayPool<byte>.Shared.Return(packBuffer);
}
}
public sealed class DisplaySignGump : Packet
{
public DisplaySignGump(Serial serial, int gumpID, string unknown, string caption) : base(0x8B)
{
unknown ??= "";
caption ??= "";
EnsureCapacity(15 + unknown.Length + caption.Length);
Stream.Write(serial);
Stream.Write((short)gumpID);
Stream.Write((short)(unknown.Length + 1));
Stream.WriteAsciiNull(unknown);
Stream.Write((short)(caption.Length + 1));
Stream.WriteAsciiNull(caption);
}
Stream.Write((short)0x04);
Stream.Write(typeID);
Stream.Write(buttonID);
}
}
public sealed class DisplayGumpPacked : Packet, IGumpWriter
{
private static readonly byte[] m_Buffer = new byte[48];
private readonly Gump m_Gump;
private readonly PacketWriter m_Layout;
private readonly PacketWriter m_Strings;
private int m_StringCount;
static DisplayGumpPacked() => m_Buffer[0] = (byte)' ';
public DisplayGumpPacked(Gump gump)
: base(0xDD)
{
m_Gump = gump;
m_Layout = PacketWriter.CreateInstance(8192);
m_Strings = PacketWriter.CreateInstance(8192);
}
public int TextEntries { get; set; }
public int Switches { get; set; }
public void AppendLayout(bool val)
{
AppendLayout(val ? " 1"u8 : " 0"u8);
}
public void AppendLayout(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(uint val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1) + 1;
m_Layout.Write(m_Buffer, 0, bytes);
}
public void AppendLayout(Serial serial) => AppendLayout(serial.Value);
public void AppendLayoutNS(int val)
{
var toString = val.ToString();
var bytes = Encoding.ASCII.GetBytes(toString, 0, toString.Length, m_Buffer, 1);
m_Layout.Write(m_Buffer, 1, bytes);
}
public void AppendLayoutNS(string text)
{
m_Layout.WriteAsciiFixed(text, text.Length);
}
public void AppendLayout(string text)
{
AppendLayout(" @"u8);
m_Layout.WriteAsciiFixed(text, text.Length);
AppendLayout("@"u8);
}
public void AppendLayout(ReadOnlySpan<byte> buffer)
{
m_Layout.Write(buffer);
}
public void WriteStrings(List<string> strings)
{
m_StringCount = strings.Count;
for (var i = 0; i < strings.Count; ++i)
{
var v = strings[i] ?? "";
m_Strings.Write((ushort)v.Length);
m_Strings.WriteBigUniFixed(v, v.Length);
}
}
public void Flush()
{
EnsureCapacity(28 + (int)m_Layout.Length + (int)m_Strings.Length);
Stream.Write(m_Gump.Serial);
Stream.Write(m_Gump.TypeID);
Stream.Write(m_Gump.X);
Stream.Write(m_Gump.Y);
// Note: layout MUST be null terminated (don't listen to krrios)
m_Layout.Write((byte)0);
WritePacked(m_Layout);
Stream.Write(m_StringCount);
WritePacked(m_Strings);
PacketWriter.ReleaseInstance(m_Layout);
PacketWriter.ReleaseInstance(m_Strings);
}
private void WritePacked(PacketWriter src)
{
var buffer = src.UnderlyingStream.GetBuffer();
var length = (int)src.Length;
if (length == 0)
{
Stream.Write(0);
return;
}
var wantLength = 1 + length * 1024 / 1000;
wantLength += 4095;
wantLength &= ~4095;
var packBuffer = ArrayPool<byte>.Shared.Rent(wantLength);
var bytesPacked = Deflate.Standard.Pack(packBuffer, buffer.AsSpan(0, length));
Stream.Write(4 + bytesPacked);
Stream.Write(length);
Stream.Write(packBuffer, 0, bytesPacked);
ArrayPool<byte>.Shared.Return(packBuffer);
}
}
public sealed class DisplaySignGump : Packet
{
public DisplaySignGump(Serial serial, int gumpID, string unknown, string caption) : base(0x8B)
{
unknown ??= "";
caption ??= "";
EnsureCapacity(15 + unknown.Length + caption.Length);
Stream.Write(serial);
Stream.Write((short)gumpID);
Stream.Write((short)(unknown.Length + 1));
Stream.WriteAsciiNull(unknown);
Stream.Write((short)(caption.Length + 1));
Stream.WriteAsciiNull(caption);
}
}

View file

@ -1,117 +1,116 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class ItemPacketTests
{
[Fact]
public void TestWorldItemPacket()
{
[Fact]
public void TestWorldItemPacket()
var serial = (Serial)0x1024;
var itemId = 1;
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
var item = new Item(serial)
{
var serial = (Serial)0x1024;
var itemId = 1;
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10),
Direction = Direction.Left
};
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
var expected = new WorldItem(item).Compile();
var item = new Item(serial)
{
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10),
Direction = Direction.Left
};
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendWorldItem(item);
var expected = new WorldItem(item).Compile();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendWorldItem(item);
[Fact]
public void TestWorldItemSAPacket()
{
var serial = (Serial)0x1024;
ushort itemId = 1;
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
[Fact]
public void TestWorldItemSAPacket()
var item = new Item(serial)
{
var serial = (Serial)0x1024;
ushort itemId = 1;
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10)
};
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
var expected = new WorldItemSA(item).Compile();
var item = new Item(serial)
{
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10)
};
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.StygianAbyss;
ns.SendWorldItem(item);
var expected = new WorldItemSA(item).Compile();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.StygianAbyss;
ns.SendWorldItem(item);
[Fact]
public void TestWorldItemHSPacket()
{
var serial = (Serial)0x1024;
var itemId = 1;
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
[Fact]
public void TestWorldItemHSPacket()
var item = new Item(serial)
{
var serial = (Serial)0x1024;
var itemId = 1;
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10)
};
// Move to fixture
TileData.ItemTable[itemId] = new ItemData(
"Test Item Data",
TileFlag.Generic,
1,
1,
1,
1,
1,
1
);
var expected = new WorldItemHS(item).Compile();
var item = new Item(serial)
{
ItemID = itemId,
Hue = 0x1024,
Amount = 10,
Location = new Point3D(1000, 100, -10)
};
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.StygianAbyss | ProtocolChanges.HighSeas;
ns.SendWorldItem(item);
var expected = new WorldItemHS(item).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.StygianAbyss | ProtocolChanges.HighSeas;
ns.SendWorldItem(item);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,208 +1,207 @@
using Server.Items;
namespace Server.Network
namespace Server.Network;
public sealed class WorldItem : Packet
{
public sealed class WorldItem : Packet
public WorldItem(Item item) : base(0x1A)
{
public WorldItem(Item item) : base(0x1A)
EnsureCapacity(20);
// 14 base length
// +2 - Amount
// +2 - Hue
// +1 - Flags
var serial = item.Serial.Value;
var itemID = item.ItemID & 0x3FFF;
var amount = item.Amount;
var loc = item.Location;
var x = loc.X;
var y = loc.Y;
var hue = item.Hue;
var flags = item.GetPacketFlags();
var direction = (int)item.Direction;
if (amount != 0)
{
EnsureCapacity(20);
// 14 base length
// +2 - Amount
// +2 - Hue
// +1 - Flags
var serial = item.Serial.Value;
var itemID = item.ItemID & 0x3FFF;
var amount = item.Amount;
var loc = item.Location;
var x = loc.X;
var y = loc.Y;
var hue = item.Hue;
var flags = item.GetPacketFlags();
var direction = (int)item.Direction;
if (amount != 0)
{
serial |= 0x80000000;
}
else
{
serial &= 0x7FFFFFFF;
}
Stream.Write(serial);
if (item is BaseMulti)
{
Stream.Write((short)(itemID | 0x4000));
}
else
{
Stream.Write((short)itemID);
}
if (amount != 0)
{
Stream.Write((short)amount);
}
x &= 0x7FFF;
if (direction != 0)
{
x |= 0x8000;
}
Stream.Write((short)x);
y &= 0x3FFF;
if (hue != 0)
{
y |= 0x8000;
}
if (flags != 0)
{
y |= 0x4000;
}
Stream.Write((short)y);
if (direction != 0)
{
Stream.Write((byte)direction);
}
Stream.Write((sbyte)loc.Z);
if (hue != 0)
{
Stream.Write((ushort)hue);
}
if (flags != 0)
{
Stream.Write((byte)flags);
}
serial |= 0x80000000;
}
}
public sealed class WorldItemSA : Packet
{
public WorldItemSA(Item item) : base(0xF3, 24)
else
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0x7FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((sbyte)loc.Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
serial &= 0x7FFFFFFF;
}
}
public sealed class WorldItemHS : Packet
{
public WorldItemHS(Item item) : base(0xF3, 26)
Stream.Write(serial);
if (item is BaseMulti)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0xFFFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((sbyte)loc.Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
Stream.Write((short)0x00); // ??
Stream.Write((short)(itemID | 0x4000));
}
}
public sealed class OPLInfo : Packet
{
/*public OPLInfo( ObjectPropertyList list ) : base( 0xBF )
else
{
EnsureCapacity( 13 );
Stream.Write((short)itemID);
}
m_Stream.Write( (short) 0x10 );
m_Stream.Write( (int) list.Entity.Serial );
m_Stream.Write( (int) list.Hash );
}*/
public OPLInfo(Serial serial, int hash) : base(0xDC, 9)
if (amount != 0)
{
Stream.Write(serial);
Stream.Write(hash);
Stream.Write((short)amount);
}
x &= 0x7FFF;
if (direction != 0)
{
x |= 0x8000;
}
Stream.Write((short)x);
y &= 0x3FFF;
if (hue != 0)
{
y |= 0x8000;
}
if (flags != 0)
{
y |= 0x4000;
}
Stream.Write((short)y);
if (direction != 0)
{
Stream.Write((byte)direction);
}
Stream.Write((sbyte)loc.Z);
if (hue != 0)
{
Stream.Write((ushort)hue);
}
if (flags != 0)
{
Stream.Write((byte)flags);
}
}
}
public sealed class WorldItemSA : Packet
{
public WorldItemSA(Item item) : base(0xF3, 24)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0x7FFF;
Stream.Write((short)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((sbyte)loc.Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
}
}
public sealed class WorldItemHS : Packet
{
public WorldItemHS(Item item) : base(0xF3, 26)
{
Stream.Write((short)0x1);
var itemID = item.ItemID;
if (item is BaseMulti)
{
Stream.Write((byte)0x02);
Stream.Write(item.Serial);
itemID &= 0x3FFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
else
{
Stream.Write((byte)0x00);
Stream.Write(item.Serial);
itemID &= 0xFFFF;
Stream.Write((ushort)itemID);
Stream.Write((byte)0);
}
var amount = item.Amount;
Stream.Write((short)amount);
Stream.Write((short)amount);
var loc = item.Location;
Stream.Write((short)loc.X);
Stream.Write((short)loc.Y);
Stream.Write((sbyte)loc.Z);
Stream.Write((byte)item.Light);
Stream.Write((short)item.Hue);
Stream.Write((byte)item.GetPacketFlags());
Stream.Write((short)0x00); // ??
}
}
public sealed class OPLInfo : Packet
{
/*public OPLInfo( ObjectPropertyList list ) : base( 0xBF )
{
EnsureCapacity( 13 );
m_Stream.Write( (short) 0x10 );
m_Stream.Write( (int) list.Entity.Serial );
m_Stream.Write( (int) list.Hash );
}*/
public OPLInfo(Serial serial, int hash) : base(0xDC, 9)
{
Stream.Write(serial);
Stream.Write(hash);
}
}

View file

@ -1,35 +1,35 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class LightPacketTests
{
public class LightPacketTests
[Fact]
public void TestGlobalLightLevel()
{
[Fact]
public void TestGlobalLightLevel()
{
const byte lightLevel = 5;
var expected = new GlobalLightLevel(lightLevel).Compile();
const byte lightLevel = 5;
var expected = new GlobalLightLevel(lightLevel).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendGlobalLightLevel(lightLevel);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendGlobalLightLevel(lightLevel);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestPersonalLightLevel()
{
var serial = (Serial)0x1024;
byte lightLevel = 5;
var expected = new PersonalLightLevel(serial, lightLevel).Compile();
[Fact]
public void TestPersonalLightLevel()
{
var serial = (Serial)0x1024;
byte lightLevel = 5;
var expected = new PersonalLightLevel(serial, lightLevel).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPersonalLightLevel(serial, lightLevel);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPersonalLightLevel(serial, lightLevel);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,35 +1,34 @@
namespace Server.Network
namespace Server.Network;
public sealed class GlobalLightLevel : Packet
{
public sealed class GlobalLightLevel : Packet
private static readonly GlobalLightLevel[] m_Cache = new GlobalLightLevel[0x100];
public GlobalLightLevel(int level) : base(0x4F, 2)
{
private static readonly GlobalLightLevel[] m_Cache = new GlobalLightLevel[0x100];
public GlobalLightLevel(int level) : base(0x4F, 2)
{
Stream.Write((sbyte)level);
}
public static GlobalLightLevel Instantiate(int level)
{
var lvl = (byte)level;
var p = m_Cache[lvl];
if (p == null)
{
m_Cache[lvl] = p = new GlobalLightLevel(level);
p.SetStatic();
}
return p;
}
Stream.Write((sbyte)level);
}
public sealed class PersonalLightLevel : Packet
public static GlobalLightLevel Instantiate(int level)
{
public PersonalLightLevel(Serial mobile, int level = 0) : base(0x4E, 6)
var lvl = (byte)level;
var p = m_Cache[lvl];
if (p == null)
{
Stream.Write(mobile);
Stream.Write((sbyte)level);
m_Cache[lvl] = p = new GlobalLightLevel(level);
p.SetStatic();
}
return p;
}
}
public sealed class PersonalLightLevel : Packet
{
public PersonalLightLevel(Serial mobile, int level = 0) : base(0x4E, 6)
{
Stream.Write(mobile);
Stream.Write((sbyte)level);
}
}

View file

@ -1,49 +1,48 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class MapPatchesTests
{
[Fact]
public void TestMapPatches()
{
[Fact]
public void TestMapPatches()
{
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
var expected = new MapPatches().Compile();
var expected = new MapPatches().Compile();
ns.SendMapPatches();
ns.SendMapPatches();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestInvalidMapEnable()
{
var expected = new InvalidMapEnable().Compile();
[Fact]
public void TestInvalidMapEnable()
{
var expected = new InvalidMapEnable().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendInvalidMap();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendInvalidMap();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData("Felucca")]
[InlineData("Malas")]
public void TestMapChange(string mapName)
{
var map = Map.Parse(mapName);
var expected = new MapChange(map).Compile();
[Theory]
[InlineData("Felucca")]
[InlineData("Malas")]
public void TestMapChange(string mapName)
{
var map = Map.Parse(mapName);
var expected = new MapChange(map).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMapChange(map);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMapChange(map);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,44 +1,43 @@
namespace Server.Network
namespace Server.Network;
public sealed class MapPatches : Packet
{
public sealed class MapPatches : Packet
public MapPatches() : base(0xBF)
{
public MapPatches() : base(0xBF)
{
EnsureCapacity(9 + 4 * 8);
EnsureCapacity(9 + 4 * 8);
Stream.Write((short)0x18);
Stream.Write((short)0x18);
Stream.Write(4);
Stream.Write(4);
Stream.Write(Map.Felucca.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Felucca.Tiles.Patch.LandBlocks);
Stream.Write(Map.Felucca.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Felucca.Tiles.Patch.LandBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.LandBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Trammel.Tiles.Patch.LandBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.LandBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Ilshenar.Tiles.Patch.LandBlocks);
Stream.Write(Map.Malas.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Malas.Tiles.Patch.LandBlocks);
}
}
public sealed class InvalidMapEnable : Packet
{
public InvalidMapEnable() : base(0xC6, 1)
{
}
}
public sealed class MapChange : Packet
{
public MapChange(Map map) : base(0xBF)
{
EnsureCapacity(6);
Stream.Write((short)0x08);
Stream.Write((byte)map.MapID);
}
Stream.Write(Map.Malas.Tiles.Patch.StaticBlocks);
Stream.Write(Map.Malas.Tiles.Patch.LandBlocks);
}
}
public sealed class InvalidMapEnable : Packet
{
public InvalidMapEnable() : base(0xC6, 1)
{
}
}
public sealed class MapChange : Packet
{
public MapChange(Map map) : base(0xBF)
{
EnsureCapacity(6);
Stream.Write((short)0x08);
Stream.Write((byte)map.MapID);
}
}

View file

@ -5,98 +5,97 @@ using Server.Menus.Questions;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
internal class ContextMenuItem : Item
{
internal class ContextMenuItem : Item
private readonly bool _requiresNewPacket;
public ContextMenuItem(Serial serial, bool requiresNewPacket) : base(serial) =>
_requiresNewPacket = requiresNewPacket;
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
{
private readonly bool _requiresNewPacket;
public ContextMenuItem(Serial serial, bool requiresNewPacket) : base(serial) =>
_requiresNewPacket = requiresNewPacket;
base.GetContextMenuEntries(from, ref list);
public override void GetContextMenuEntries(Mobile from, ref PooledRefList<ContextMenuEntry> list)
list.Add(new ContextMenuEntry(3000001));
list.Add(new ContextMenuEntry(3000002));
list.Add(new ContextMenuEntry(3000003));
if (_requiresNewPacket)
{
base.GetContextMenuEntries(from, ref list);
list.Add(new ContextMenuEntry(3000001));
list.Add(new ContextMenuEntry(3000002));
list.Add(new ContextMenuEntry(3000003));
if (_requiresNewPacket)
{
list.Add(new ContextMenuEntry(500000));
}
}
}
[Collection("Sequential Server Tests")]
public class MenuPacketTests
{
[Fact]
public void TestDisplayItemListMenu()
{
var menu = new ItemListMenu(
"Which item would you choose?",
[
new ItemListEntry("Item 1", 0x01),
new ItemListEntry("Item 2", 0x100),
new ItemListEntry("Item 3", 0x1000, 250)
]
);
var expected = new DisplayItemListMenu(menu).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayItemListMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestDisplayQuestionMenu()
{
var menu = new QuestionMenu(
"Which option would you choose?",
[
"Option 1",
"Option 2",
"Option 3"
]
);
var expected = new DisplayQuestionMenu(menu).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayQuestionMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
public void TestDisplayContextMenu(bool newHaven, bool newPacket)
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var item = new ContextMenuItem(World.NewItem, newPacket);
var menu = ContextMenuSystem.CreateContextMenu(m, item);
var packet = newHaven && newPacket ? (Packet)new DisplayContextMenu(menu) : new DisplayContextMenuOld(menu);
var expected = packet.Compile();
var ns = PacketTestUtilities.CreateTestNetState();
if (newHaven)
{
ns.ProtocolChanges |= ProtocolChanges.NewHaven;
}
ns.SendDisplayContextMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
list.Add(new ContextMenuEntry(500000));
}
}
}
[Collection("Sequential Server Tests")]
public class MenuPacketTests
{
[Fact]
public void TestDisplayItemListMenu()
{
var menu = new ItemListMenu(
"Which item would you choose?",
[
new ItemListEntry("Item 1", 0x01),
new ItemListEntry("Item 2", 0x100),
new ItemListEntry("Item 3", 0x1000, 250)
]
);
var expected = new DisplayItemListMenu(menu).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayItemListMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestDisplayQuestionMenu()
{
var menu = new QuestionMenu(
"Which option would you choose?",
[
"Option 1",
"Option 2",
"Option 3"
]
);
var expected = new DisplayQuestionMenu(menu).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayQuestionMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(false, false)]
[InlineData(false, true)]
[InlineData(true, false)]
[InlineData(true, true)]
public void TestDisplayContextMenu(bool newHaven, bool newPacket)
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var item = new ContextMenuItem(World.NewItem, newPacket);
var menu = ContextMenuSystem.CreateContextMenu(m, item);
var packet = newHaven && newPacket ? (Packet)new DisplayContextMenu(menu) : new DisplayContextMenuOld(menu);
var expected = packet.Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
if (newHaven)
{
ns.ProtocolChanges |= ProtocolChanges.NewHaven;
}
ns.SendDisplayContextMenu(menu);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -3,218 +3,217 @@ using Server.Menus;
using Server.Menus.ItemLists;
using Server.Menus.Questions;
namespace Server.Network
namespace Server.Network;
public sealed class DisplayItemListMenu : Packet
{
public sealed class DisplayItemListMenu : Packet
public DisplayItemListMenu(ItemListMenu menu) : base(0x7C)
{
public DisplayItemListMenu(ItemListMenu menu) : base(0x7C)
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
EnsureCapacity(256);
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var entries = menu.Entries;
var question = menu.Question;
int entriesLength = (byte)entries.Length;
if (question == null)
Stream.Write((byte)entriesLength);
for (var i = 0; i < entriesLength; ++i)
{
var e = entries[i];
Stream.Write((ushort)e.ItemID);
Stream.Write((short)e.Hue);
var name = e.Name;
if (name == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var entries = menu.Entries;
int entriesLength = (byte)entries.Length;
Stream.Write((byte)entriesLength);
for (var i = 0; i < entriesLength; ++i)
{
var e = entries[i];
Stream.Write((ushort)e.ItemID);
Stream.Write((short)e.Hue);
var name = e.Name;
if (name == null)
{
Stream.Write((byte)0);
}
else
{
var nameLength = name.Length;
Stream.Write((byte)nameLength);
Stream.WriteAsciiFixed(name, nameLength);
}
}
}
}
public sealed class DisplayQuestionMenu : Packet
{
public DisplayQuestionMenu(QuestionMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var answers = menu.Answers;
int answersLength = (byte)answers.Length;
Stream.Write((byte)answersLength);
for (var i = 0; i < answersLength; ++i)
{
Stream.Write(0);
var answer = answers[i];
if (answer == null)
{
Stream.Write((byte)0);
}
else
{
var answerLength = answer.Length;
Stream.Write((byte)answerLength);
Stream.WriteAsciiFixed(answer, answerLength);
}
}
}
}
public sealed class DisplayContextMenu : Packet
{
public DisplayContextMenu(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x02);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write(e.Number);
Stream.Write((short)i);
var range = e.Range;
if (range == -1)
{
range = Core.GlobalUpdateRange;
}
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
{
flags |= CMEFlags.Disabled;
}
Stream.Write((short)flags);
}
}
}
public sealed class DisplayContextMenuOld : Packet
{
public DisplayContextMenuOld(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x01);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write((short)i);
Stream.Write((ushort)(e.Number - 3000000));
var range = e.Range;
if (range == -1)
{
range = Core.GlobalUpdateRange;
}
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
{
flags |= CMEFlags.Disabled;
}
var color = e.Color & 0xFFFF;
if (color != 0xFFFF)
{
flags |= CMEFlags.Colored;
}
Stream.Write((short)flags);
if ((flags & CMEFlags.Colored) != 0)
{
Stream.Write((short)color);
}
var nameLength = name.Length;
Stream.Write((byte)nameLength);
Stream.WriteAsciiFixed(name, nameLength);
}
}
}
}
public sealed class DisplayQuestionMenu : Packet
{
public DisplayQuestionMenu(QuestionMenu menu) : base(0x7C)
{
EnsureCapacity(256);
Stream.Write(((IMenu)menu).Serial);
Stream.Write((short)0);
var question = menu.Question;
if (question == null)
{
Stream.Write((byte)0);
}
else
{
var questionLength = question.Length;
Stream.Write((byte)questionLength);
Stream.WriteAsciiFixed(question, questionLength);
}
var answers = menu.Answers;
int answersLength = (byte)answers.Length;
Stream.Write((byte)answersLength);
for (var i = 0; i < answersLength; ++i)
{
Stream.Write(0);
var answer = answers[i];
if (answer == null)
{
Stream.Write((byte)0);
}
else
{
var answerLength = answer.Length;
Stream.Write((byte)answerLength);
Stream.WriteAsciiFixed(answer, answerLength);
}
}
}
}
public sealed class DisplayContextMenu : Packet
{
public DisplayContextMenu(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x02);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write(e.Number);
Stream.Write((short)i);
var range = e.Range;
if (range == -1)
{
range = Core.GlobalUpdateRange;
}
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
{
flags |= CMEFlags.Disabled;
}
Stream.Write((short)flags);
}
}
}
public sealed class DisplayContextMenuOld : Packet
{
public DisplayContextMenuOld(ContextMenu menu) : base(0xBF)
{
var entries = menu.Entries;
int length = (byte)entries.Length;
EnsureCapacity(12 + length * 8);
Stream.Write((short)0x14);
Stream.Write((short)0x01);
var target = menu.Target;
Stream.Write(target.Serial);
Stream.Write((byte)length);
var p = target switch
{
Mobile _ => target.Location,
Item item => item.GetWorldLocation(),
_ => Point3D.Zero
};
for (var i = 0; i < length; ++i)
{
var e = entries[i];
Stream.Write((short)i);
Stream.Write((ushort)(e.Number - 3000000));
var range = e.Range;
if (range == -1)
{
range = Core.GlobalUpdateRange;
}
var flags = e.Flags;
if (!(e.Enabled && menu.From.InRange(p, range)))
{
flags |= CMEFlags.Disabled;
}
var color = e.Color & 0xFFFF;
if (color != 0xFFFF)
{
flags |= CMEFlags.Colored;
}
Stream.Write((short)flags);
if ((flags & CMEFlags.Colored) != 0)
{
Stream.Write((short)color);
}
}
}
}

View file

@ -2,221 +2,222 @@ using Server.Network;
using Server.Prompts;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class MessageTests
{
public class MessageTests
[Fact]
public void TestMessageLocalized()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var number = 150000;
var name = "Stuff";
var args = "Arguments";
var expected = new MessageLocalized(
serial,
graphic,
messageType,
hue,
font,
number,
name,
args
).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessageLocalized(
serial,
graphic,
messageType,
hue,
font,
number,
name,
args
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMessageLocalizedAffix()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var number = 150000;
var name = "Stuff";
var args = "Arguments";
var affixType = AffixType.System;
var affix = "Affix";
var expected = new MessageLocalizedAffix(
serial,
graphic,
messageType,
hue,
font,
number,
name,
affixType,
affix,
args
).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessageLocalizedAffix(
serial,
graphic,
messageType,
hue,
font,
number,
name,
affixType,
affix,
args
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestAsciiMessage()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var name = "Stuff";
var text = "Some Text";
var expected = new AsciiMessage(
serial,
graphic,
messageType,
hue,
font,
name,
text
).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessage(
serial,
graphic,
messageType,
hue,
font,
true,
null,
name,
text
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestUnicodeMessage()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var lang = "ENU";
var name = "Stuff";
var text = "Some Text";
var expected = new UnicodeMessage(
serial,
graphic,
messageType,
hue,
font,
lang,
name,
text
).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessage(
serial,
graphic,
messageType,
hue,
font,
false,
lang,
name,
text
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestFollowMessage()
{
var serial = (Serial)0x1024;
var serial2 = (Serial)0x2;
var expected = new FollowMessage(serial, serial2).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendFollowMessage(serial, serial2);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestObjectHelpResponse()
{
var s = (Serial)0x100;
var text = "This is some testing text";
var expected = new ObjectHelpResponse(s, text).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendHelpResponse(s, text);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
internal class TestPrompt : Prompt
{
}
[Collection("Sequential Server Tests")]
public class UnicodePromptTests
{
[Fact]
public void TestMessageLocalized()
public void TestUnicodePrompt()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var number = 150000;
var name = "Stuff";
var args = "Arguments";
var prompt = new TestPrompt();
var expected = new UnicodePrompt(prompt).Compile();
var expected = new MessageLocalized(
serial,
graphic,
messageType,
hue,
font,
number,
name,
args
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessageLocalized(
serial,
graphic,
messageType,
hue,
font,
number,
name,
args
);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPrompt(prompt);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMessageLocalizedAffix()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var number = 150000;
var name = "Stuff";
var args = "Arguments";
var affixType = AffixType.System;
var affix = "Affix";
var expected = new MessageLocalizedAffix(
serial,
graphic,
messageType,
hue,
font,
number,
name,
affixType,
affix,
args
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessageLocalizedAffix(
serial,
graphic,
messageType,
hue,
font,
number,
name,
affixType,
affix,
args
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestAsciiMessage()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var name = "Stuff";
var text = "Some Text";
var expected = new AsciiMessage(
serial,
graphic,
messageType,
hue,
font,
name,
text
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessage(
serial,
graphic,
messageType,
hue,
font,
true,
null,
name,
text
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestUnicodeMessage()
{
var serial = (Serial)0x1024;
var graphic = 0x100;
var messageType = MessageType.Label;
var hue = 1024;
var font = 3;
var lang = "ENU";
var name = "Stuff";
var text = "Some Text";
var expected = new UnicodeMessage(
serial,
graphic,
messageType,
hue,
font,
lang,
name,
text
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMessage(
serial,
graphic,
messageType,
hue,
font,
false,
lang,
name,
text
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestFollowMessage()
{
var serial = (Serial)0x1024;
var serial2 = (Serial)0x2;
var expected = new FollowMessage(serial, serial2).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendFollowMessage(serial, serial2);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestObjectHelpResponse()
{
var s = (Serial)0x100;
var text = "This is some testing text";
var expected = new ObjectHelpResponse(s, text).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendHelpResponse(s, text);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
internal class TestPrompt : Prompt
{
}
public class UnicodePromptTests
{
[Fact]
public void TestUnicodePrompt()
{
var prompt = new TestPrompt();
var expected = new UnicodePrompt(prompt).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPrompt(prompt);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}
}
}

View file

@ -1,155 +1,154 @@
using Server.Prompts;
namespace Server.Network
namespace Server.Network;
public sealed class MessageLocalized : Packet
{
public sealed class MessageLocalized : Packet
public MessageLocalized(
Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, string args
) : base(0xC1)
{
public MessageLocalized(
Serial serial, int graphic, MessageType type, int hue, int font, int number, string name, string args
) : base(0xC1)
name ??= "";
args ??= "";
if (hue == 0)
{
name ??= "";
args ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(50 + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteLittleUniNull(args);
hue = 0x3B2;
}
}
public sealed class MessageLocalizedAffix : Packet
{
public MessageLocalizedAffix(
Serial serial, int graphic, MessageType messageType, int hue, int font, int number,
string name, AffixType affixType, string affix, string args
) : base(0xCC)
{
name ??= "";
affix ??= "";
args ??= "";
EnsureCapacity(50 + args.Length * 2);
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(52 + affix.Length + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)messageType);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.Write((byte)affixType);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(affix);
Stream.WriteBigUniNull(args);
}
}
public sealed class AsciiMessage : Packet
{
public AsciiMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string name, string text
) : base(0x1C)
{
name ??= "";
text ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(45 + text.Length);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(text);
}
}
public sealed class UnicodeMessage : Packet
{
public UnicodeMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name,
string text
) : base(0xAE)
{
if (string.IsNullOrEmpty(lang))
{
lang = "ENU";
}
name ??= "";
text ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(50 + text.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(lang, 4);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteBigUniNull(text);
}
}
public sealed class FollowMessage : Packet
{
public FollowMessage(Serial serial1, Serial serial2) : base(0x15, 9)
{
Stream.Write(serial1);
Stream.Write(serial2);
}
}
public sealed class UnicodePrompt : Packet
{
public UnicodePrompt(Prompt prompt) : base(0xC2)
{
EnsureCapacity(21);
Stream.Write(prompt.Serial); // TODO: Does this value even matter?
Stream.Write(prompt.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write((short)0);
}
}
public sealed class ObjectHelpResponse : Packet
{
public ObjectHelpResponse(Serial e, string text) : base(0xB7)
{
EnsureCapacity(9 + text.Length * 2);
Stream.Write(e);
Stream.WriteBigUniNull(text);
}
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteLittleUniNull(args);
}
}
public sealed class MessageLocalizedAffix : Packet
{
public MessageLocalizedAffix(
Serial serial, int graphic, MessageType messageType, int hue, int font, int number,
string name, AffixType affixType, string affix, string args
) : base(0xCC)
{
name ??= "";
affix ??= "";
args ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(52 + affix.Length + args.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)messageType);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.Write(number);
Stream.Write((byte)affixType);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(affix);
Stream.WriteBigUniNull(args);
}
}
public sealed class AsciiMessage : Packet
{
public AsciiMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string name, string text
) : base(0x1C)
{
name ??= "";
text ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(45 + text.Length);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteAsciiNull(text);
}
}
public sealed class UnicodeMessage : Packet
{
public UnicodeMessage(
Serial serial, int graphic, MessageType type, int hue, int font, string lang, string name,
string text
) : base(0xAE)
{
if (string.IsNullOrEmpty(lang))
{
lang = "ENU";
}
name ??= "";
text ??= "";
if (hue == 0)
{
hue = 0x3B2;
}
EnsureCapacity(50 + text.Length * 2);
Stream.Write(serial);
Stream.Write((short)graphic);
Stream.Write((byte)type);
Stream.Write((short)hue);
Stream.Write((short)font);
Stream.WriteAsciiFixed(lang, 4);
Stream.WriteAsciiFixed(name, 30);
Stream.WriteBigUniNull(text);
}
}
public sealed class FollowMessage : Packet
{
public FollowMessage(Serial serial1, Serial serial2) : base(0x15, 9)
{
Stream.Write(serial1);
Stream.Write(serial2);
}
}
public sealed class UnicodePrompt : Packet
{
public UnicodePrompt(Prompt prompt) : base(0xC2)
{
EnsureCapacity(21);
Stream.Write(prompt.Serial); // TODO: Does this value even matter?
Stream.Write(prompt.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write((short)0);
}
}
public sealed class ObjectHelpResponse : Packet
{
public ObjectHelpResponse(Serial e, string text) : base(0xB7)
{
EnsureCapacity(9 + text.Length * 2);
Stream.Write(e);
Stream.WriteBigUniNull(text);
}
}

View file

@ -14,7 +14,7 @@ public class MobilePacketTests
var expected = new DeathAnimation(killed, corpse).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDeathAnimation(killed, corpse);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -29,7 +29,7 @@ public class MobilePacketTests
var expected = new BondedStatus(petSerial, bonded).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBondedStatus(petSerial, bonded);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -46,7 +46,7 @@ public class MobilePacketTests
var noto = 10;
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = protocolChanges;
var expected = new MobileMoving(m, noto, ns.StygianAbyss).Compile();
@ -67,7 +67,7 @@ public class MobilePacketTests
var expected = new MobileName(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileName(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -91,7 +91,7 @@ public class MobilePacketTests
delay
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileAnimation(
mobile,
action,
@ -120,7 +120,7 @@ public class MobilePacketTests
delay
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendNewMobileAnimation(
mobile,
action,
@ -145,7 +145,7 @@ public class MobilePacketTests
var expected = new HealthbarPoison(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileHealthbar(m, Healthbar.Poison);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -166,7 +166,7 @@ public class MobilePacketTests
var expected = new HealthbarYellow(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileHealthbar(m, Healthbar.Yellow);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -189,7 +189,7 @@ public class MobilePacketTests
var expected = new MobileStatusCompact(canBeRenamed, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileStatusCompact(m, canBeRenamed);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -219,7 +219,7 @@ public class MobilePacketTests
beheld.Dex = 25;
beheld.Stam = 100;
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
var expected = new MobileStatus(beholder, beheld, ns).Compile();
@ -255,7 +255,7 @@ public class MobilePacketTests
m.Dex = 25;
m.Stam = 100;
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
ns.Version = new ClientVersion(version);
ns.Flags = clientFlags;
@ -278,7 +278,7 @@ public class MobilePacketTests
m.DefaultMobileInit();
m.SolidHueOverride = solidHueOverride;
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
var expected = new MobileUpdate(m, ns.StygianAbyss).Compile();
@ -333,7 +333,7 @@ public class MobilePacketTests
beheld.FacialHairItemID = facialHairItemId;
beheld.FacialHairHue = facialHairHue;
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
var expected = new MobileIncoming(ns, beholder, beheld).Compile();
@ -353,7 +353,7 @@ public class MobilePacketTests
var expected = new MobileHits(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileHits(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -370,7 +370,7 @@ public class MobilePacketTests
var expected = new MobileHitsN(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileHits(m, true);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -387,7 +387,7 @@ public class MobilePacketTests
var expected = new MobileMana(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileMana(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -404,7 +404,7 @@ public class MobilePacketTests
var expected = new MobileManaN(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileMana(m, true);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -421,7 +421,7 @@ public class MobilePacketTests
var expected = new MobileStam(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileStam(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -438,7 +438,7 @@ public class MobilePacketTests
var expected = new MobileStamN(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileStam(m, true);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -459,7 +459,7 @@ public class MobilePacketTests
var expected = new MobileAttributes(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileAttributes(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -480,7 +480,7 @@ public class MobilePacketTests
var expected = new MobileAttributesN(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMobileAttributes(m, true);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -493,7 +493,7 @@ public class MobilePacketTests
var e = (Serial)0x1000;
var expected = new RemoveEntity(e).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRemoveEntity(e);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -1,71 +1,70 @@
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class MovementPacketTests
{
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(2)]
public void TestSpeedControl(byte speedControl)
{
[Theory]
[InlineData(0)]
[InlineData(1)]
[InlineData(2)]
public void TestSpeedControl(byte speedControl)
{
var expected = new SpeedControl(speedControl).Compile();
var expected = new SpeedControl(speedControl).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSpeedControl((SpeedControlSetting)speedControl);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSpeedControl((SpeedControlSetting)speedControl);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMovePlayer()
{
const Direction d = Direction.Left;
var expected = new MovePlayer(d).Compile();
[Fact]
public void TestMovePlayer()
{
const Direction d = Direction.Left;
var expected = new MovePlayer(d).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovePlayer(d);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovePlayer(d);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMovementRej()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
[Fact]
public void TestMovementRej()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
const byte seq = 100;
const byte seq = 100;
var expected = new MovementRej(seq, m).Compile();
var expected = new MovementRej(seq, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovementRej(seq, m);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovementRej(seq, m);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMovementAck()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
[Fact]
public void TestMovementAck()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
const byte seq = 100;
const byte seq = 100;
var expected = MovementAck.Instantiate(seq, m).Compile();
var expected = MovementAck.Instantiate(seq, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovementAck(seq, m);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMovementAck(seq, m);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,68 +1,67 @@
namespace Server.Network
namespace Server.Network;
public sealed class SpeedControl : Packet
{
public sealed class SpeedControl : Packet
public static readonly Packet WalkSpeed = SetStatic(new SpeedControl(2));
public static readonly Packet MountSpeed = SetStatic(new SpeedControl(1));
public static readonly Packet Disable = SetStatic(new SpeedControl(0));
public SpeedControl(int speedControl) : base(0xBF)
{
public static readonly Packet WalkSpeed = SetStatic(new SpeedControl(2));
public static readonly Packet MountSpeed = SetStatic(new SpeedControl(1));
public static readonly Packet Disable = SetStatic(new SpeedControl(0));
EnsureCapacity(6);
public SpeedControl(int speedControl) : base(0xBF)
{
EnsureCapacity(6);
Stream.Write((short)0x26);
Stream.Write((byte)speedControl);
}
}
/// <summary>
/// Causes the client to walk in a given direction. It does not send a movement request.
/// </summary>
public sealed class MovePlayer : Packet
{
public MovePlayer(Direction d) : base(0x97, 2)
{
Stream.Write((byte)d);
// @4C63B0
}
}
public sealed class MovementRej : Packet
{
public MovementRej(int seq, Mobile m) : base(0x21, 8)
{
Stream.Write((byte)seq);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((byte)m.Direction);
Stream.Write((sbyte)m.Z);
}
}
public sealed class MovementAck : Packet
{
private static readonly MovementAck[] m_Cache = new MovementAck[8 * 256];
private MovementAck(int seq, int noto) : base(0x22, 3)
{
Stream.Write((byte)seq);
Stream.Write((byte)noto);
}
public static MovementAck Instantiate(int seq, Mobile m)
{
var noto = Notoriety.Compute(m, m);
var p = m_Cache[noto * seq];
if (p == null)
{
m_Cache[noto * seq] = p = new MovementAck(seq, noto);
p.SetStatic();
}
return p;
}
Stream.Write((short)0x26);
Stream.Write((byte)speedControl);
}
}
/// <summary>
/// Causes the client to walk in a given direction. It does not send a movement request.
/// </summary>
public sealed class MovePlayer : Packet
{
public MovePlayer(Direction d) : base(0x97, 2)
{
Stream.Write((byte)d);
// @4C63B0
}
}
public sealed class MovementRej : Packet
{
public MovementRej(int seq, Mobile m) : base(0x21, 8)
{
Stream.Write((byte)seq);
Stream.Write((short)m.X);
Stream.Write((short)m.Y);
Stream.Write((byte)m.Direction);
Stream.Write((sbyte)m.Z);
}
}
public sealed class MovementAck : Packet
{
private static readonly MovementAck[] m_Cache = new MovementAck[8 * 256];
private MovementAck(int seq, int noto) : base(0x22, 3)
{
Stream.Write((byte)seq);
Stream.Write((byte)noto);
}
public static MovementAck Instantiate(int seq, Mobile m)
{
var noto = Notoriety.Compute(m, m);
var p = m_Cache[noto * seq];
if (p == null)
{
m_Cache[noto * seq] = p = new MovementAck(seq, noto);
p.SetStatic();
}
return p;
}
}

View file

@ -3,296 +3,295 @@ using Server.HuePickers;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class PlayerPacketTests
{
[Collection("Sequential Server Tests")]
public class PlayerPacketTests
[Theory]
[InlineData(StatLockType.Down, StatLockType.Up, StatLockType.Locked)]
public void TestStatLockInfo(StatLockType str, StatLockType intel, StatLockType dex)
{
[Theory]
[InlineData(StatLockType.Down, StatLockType.Up, StatLockType.Locked)]
public void TestStatLockInfo(StatLockType str, StatLockType intel, StatLockType dex)
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.StrLock = str;
m.IntLock = intel;
m.DexLock = dex;
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
m.StrLock = str;
m.IntLock = intel;
m.DexLock = dex;
var expected = new StatLockInfo(m).Compile();
var expected = new StatLockInfo(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendStatLockInfo(m);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendStatLockInfo(m);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(200)]
public void TestChangeUpdateRange(int range)
{
var expected = new ChangeUpdateRange(range).Compile();
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(200)]
public void TestChangeUpdateRange(int range)
{
var expected = new ChangeUpdateRange(range).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChangeUpdateRange((byte)range);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChangeUpdateRange((byte)range);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestDeathStatus()
{
var expected = new DeathStatus(false).Compile();
[Fact]
public void TestDeathStatus()
{
var expected = new DeathStatus(false).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDeathStatus();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDeathStatus();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0x1000u, "This is a header", "This is a body", "This is a footer")]
[InlineData(0x1000u, null, null, null)]
public void TestDisplayProfile(uint serial, string header, string body, string footer)
{
var expected = new DisplayProfile((Serial)serial, header, body, footer).Compile();
[Theory]
[InlineData(0x1000u, "This is a header", "This is a body", "This is a footer")]
[InlineData(0x1000u, null, null, null)]
public void TestDisplayProfile(uint serial, string header, string body, string footer)
{
var expected = new DisplayProfile((Serial)serial, header, body, footer).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayProfile((Serial)serial, header, body, footer);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayProfile((Serial)serial, header, body, footer);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(LRReason.CannotLift)]
[InlineData(LRReason.TryToSteal)]
public void TestLiftRej(LRReason reason)
{
var expected = new LiftRej(reason).Compile();
[Theory]
[InlineData(LRReason.CannotLift)]
[InlineData(LRReason.TryToSteal)]
public void TestLiftRej(LRReason reason)
{
var expected = new LiftRej(reason).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLiftReject(reason);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLiftReject(reason);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestLogoutAck()
{
var expected = new LogoutAck().Compile();
[Fact]
public void TestLogoutAck()
{
var expected = new LogoutAck().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLogoutAck();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLogoutAck();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(1, 2, 3)]
[InlineData(4, 5, 6)]
[InlineData(0x1234, 0x5678, 0x9ABC)]
public void TestWeather(int type, int density, int temp)
{
var expected = new Weather(type, density, temp).Compile();
[Theory]
[InlineData(1, 2, 3)]
[InlineData(4, 5, 6)]
[InlineData(0x1234, 0x5678, 0x9ABC)]
public void TestWeather(int type, int density, int temp)
{
var expected = new Weather(type, density, temp).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendWeather((byte)type, (byte)density, (byte)temp);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendWeather((byte)type, (byte)density, (byte)temp);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(100, 1000, 1, 0)]
public void TestServerChange(int x, int y, int z, int mapID)
{
var p = new Point3D(x, y, z);
var map = Map.Maps[mapID];
var expected = new ServerChange(p, map).Compile();
[Theory]
[InlineData(100, 1000, 1, 0)]
public void TestServerChange(int x, int y, int z, int mapID)
{
var p = new Point3D(x, y, z);
var map = Map.Maps[mapID];
var expected = new ServerChange(p, map).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendServerChange(p, map);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendServerChange(p, map);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(255)]
public void TestSequence(byte num)
{
var expected = new Sequence(num).Compile();
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(255)]
public void TestSequence(byte num)
{
var expected = new Sequence(num).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSequence(num);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSequence(num);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("This is a URL, I promise")]
[InlineData("https://www.modernuo.com")]
public void TestLaunchBrowser(string uri)
{
var expected = new LaunchBrowser(uri).Compile();
[Theory]
[InlineData(null)]
[InlineData("")]
[InlineData("This is a URL, I promise")]
[InlineData("https://www.modernuo.com")]
public void TestLaunchBrowser(string uri)
{
var expected = new LaunchBrowser(uri).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLaunchBrowser(uri);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendLaunchBrowser(uri);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0x1000u, 1000, 100, 10, 0x2000u, 1125, 125, 5, 0x384, 1024, 25)]
public void TestDragEffect(
uint srcSerial, int srcX, int srcY, int srcZ,
uint trgSerial, int trgX, int trgY, int trgZ,
int itemId, int hue, int amount
)
{
var src = new Entity((Serial)srcSerial, new Point3D(srcX, srcY, srcZ), null);
var targ = new Entity((Serial)trgSerial, new Point3D(trgX, trgY, trgZ), null);
[Theory]
[InlineData(0x1000u, 1000, 100, 10, 0x2000u, 1125, 125, 5, 0x384, 1024, 25)]
public void TestDragEffect(
uint srcSerial, int srcX, int srcY, int srcZ,
uint trgSerial, int trgX, int trgY, int trgZ,
int itemId, int hue, int amount
)
{
var src = new Entity((Serial)srcSerial, new Point3D(srcX, srcY, srcZ), null);
var targ = new Entity((Serial)trgSerial, new Point3D(trgX, trgY, trgZ), null);
var expected = new DragEffect(src, targ, itemId, hue, amount).Compile();
var expected = new DragEffect(src, targ, itemId, hue, amount).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDragEffect(
src.Serial, src.Location,
targ.Serial, targ.Location,
itemId, hue, amount
);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDragEffect(
src.Serial, src.Location,
targ.Serial, targ.Location,
itemId, hue, amount
);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(1, false)]
[InlineData(2, true)]
public void TestSeasonChange(int season, bool playSound)
{
var expected = new SeasonChange(season, playSound).Compile();
[Theory]
[InlineData(1, false)]
[InlineData(2, true)]
public void TestSeasonChange(int season, bool playSound)
{
var expected = new SeasonChange(season, playSound).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSeasonChange((byte)season, playSound);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSeasonChange((byte)season, playSound);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0x1024u, "Test Title", true, true)]
[InlineData(0x1024u, "Test Title", false, true)]
[InlineData(0x1024u, "Test Title", true, false)]
public void TestDisplayPaperdoll(uint m, string title, bool warmode, bool canLift)
{
var expected = new DisplayPaperdoll((Serial)m, title, warmode, canLift).Compile();
[Theory]
[InlineData(0x1024u, "Test Title", true, true)]
[InlineData(0x1024u, "Test Title", false, true)]
[InlineData(0x1024u, "Test Title", true, false)]
public void TestDisplayPaperdoll(uint m, string title, bool warmode, bool canLift)
{
var expected = new DisplayPaperdoll((Serial)m, title, warmode, canLift).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayPaperdoll((Serial)m, title, warmode, canLift);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayPaperdoll((Serial)m, title, warmode, canLift);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(MusicName.Approach)]
[InlineData(MusicName.Combat1)]
[InlineData(MusicName.ValoriaShips)]
public void TestPlayMusic(MusicName music)
{
var expected = new PlayMusic(music).Compile();
[Theory]
[InlineData(MusicName.Approach)]
[InlineData(MusicName.Combat1)]
[InlineData(MusicName.ValoriaShips)]
public void TestPlayMusic(MusicName music)
{
var expected = new PlayMusic(music).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPlayMusic(music);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPlayMusic(music);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(10, 1, "Some text")]
[InlineData(100, 10, "Some more text")]
public void TestScrollMessage(int type, int tip, string text)
{
var expected = new ScrollMessage(type, tip, text).Compile();
[Theory]
[InlineData(10, 1, "Some text")]
[InlineData(100, 10, "Some more text")]
public void TestScrollMessage(int type, int tip, string text)
{
var expected = new ScrollMessage(type, tip, text).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendScrollMessage(type, tip ,text);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendScrollMessage(type, tip ,text);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(14, 10, 05)]
public void TestCurrentTime(int hour, int minute, int second)
{
var date = new DateTime(2020, 1, 1, hour, minute, second);
var expected = new CurrentTime(date).Compile();
[Theory]
[InlineData(14, 10, 05)]
public void TestCurrentTime(int hour, int minute, int second)
{
var date = new DateTime(2020, 1, 1, hour, minute, second);
var expected = new CurrentTime(date).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCurrentTime(date);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCurrentTime(date);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(1000, 10, 1)]
public void TestPathfindMessage(int x, int y, int z)
{
var p = new Point3D(x, y, z);
var expected = new PathfindMessage(p).Compile();
[Theory]
[InlineData(1000, 10, 1)]
public void TestPathfindMessage(int x, int y, int z)
{
var p = new Point3D(x, y, z);
var expected = new PathfindMessage(p).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPathfindMessage(p);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPathfindMessage(p);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
public void TestPingAck(byte ping)
{
var expected = new PingAck(ping).Compile();
[Theory]
[InlineData(0)]
[InlineData(10)]
[InlineData(100)]
public void TestPingAck(byte ping)
{
var expected = new PingAck(ping).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPingAck(ping);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPingAck(ping);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(0xFF01)]
public void TestDisplayHuePicker(int itemID)
{
var huePicker = new HuePicker(itemID);
[Theory]
[InlineData(0xFF01)]
public void TestDisplayHuePicker(int itemID)
{
var huePicker = new HuePicker(itemID);
var expected = new DisplayHuePicker(huePicker).Compile();
var expected = new DisplayHuePicker(huePicker).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayHuePicker(huePicker.Serial, huePicker.ItemID);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayHuePicker(huePicker.Serial, huePicker.ItemID);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,373 +1,372 @@
using System;
using Server.HuePickers;
namespace Server.Network
namespace Server.Network;
public sealed class StatLockInfo : Packet
{
public sealed class StatLockInfo : Packet
public StatLockInfo(Mobile m) : base(0xBF)
{
public StatLockInfo(Mobile m) : base(0xBF)
{
EnsureCapacity(12);
EnsureCapacity(12);
Stream.Write((short)0x19);
Stream.Write((byte)2);
Stream.Write(m.Serial);
Stream.Write((byte)0);
Stream.Write((short)0x19);
Stream.Write((byte)2);
Stream.Write(m.Serial);
Stream.Write((byte)0);
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
var lockBits = ((int)m.StrLock << 4) | ((int)m.DexLock << 2) | (int)m.IntLock;
Stream.Write((byte)lockBits);
}
}
public sealed class ChangeUpdateRange : Packet
{
private static readonly ChangeUpdateRange[] m_Cache = new ChangeUpdateRange[0x100];
public ChangeUpdateRange(int range) : base(0xC8, 2)
{
Stream.Write((byte)range);
}
public static ChangeUpdateRange Instantiate(int range)
{
var idx = (byte)range;
var p = m_Cache[idx];
if (p == null)
{
m_Cache[idx] = p = new ChangeUpdateRange(range);
p.SetStatic();
}
return p;
}
}
public sealed class DeathStatus : Packet
{
public static readonly Packet Dead = SetStatic(new DeathStatus(true));
public static readonly Packet Alive = SetStatic(new DeathStatus(false));
public DeathStatus(bool dead) : base(0x2C, 2)
{
Stream.Write((byte)(dead ? 0 : 2));
}
public static Packet Instantiate(bool dead) => dead ? Dead : Alive;
}
public sealed class DisplayProfile : Packet
{
public DisplayProfile(Serial m, string header, string body, string footer) : base(0xB8)
{
header ??= "";
body ??= "";
footer ??= "";
EnsureCapacity(12 + header.Length + footer.Length * 2 + body.Length * 2);
Stream.Write(m);
Stream.WriteAsciiNull(header);
Stream.WriteBigUniNull(footer);
Stream.WriteBigUniNull(body);
}
}
public sealed class LiftRej : Packet
{
public LiftRej(LRReason reason) : base(0x27, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class LogoutAck : Packet
{
public LogoutAck() : base(0xD1, 2)
{
Stream.Write((byte)0x01);
}
}
public sealed class Weather : Packet
{
public Weather(int type, int density, int temp) : base(0x65, 4)
{
Stream.Write((byte)type);
Stream.Write((byte)density);
Stream.Write((byte)temp);
}
}
public sealed class ServerChange : Packet
{
public ServerChange(Point3D p, Map map) : base(0x76, 16)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
Stream.Write((byte)0);
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)map.Width);
Stream.Write((short)map.Height);
}
}
public sealed class SkillUpdate : Packet
{
public SkillUpdate(Skills skills) : base(0x3A)
{
EnsureCapacity(6 + skills.Length * 9);
Stream.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
var s = skills[i];
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((ushort)(s.Info.SkillID + 1));
Stream.Write((ushort)uv);
Stream.Write((ushort)s.BaseFixedPoint);
Stream.Write((byte)s.Lock);
Stream.Write((ushort)s.CapFixedPoint);
}
Stream.Write((short)0); // terminate
}
}
public sealed class Sequence : Packet
{
public Sequence(int num) : base(0x7B, 2)
{
Stream.Write((byte)num);
}
}
public sealed class SkillChange : Packet
{
public SkillChange(Skill skill) : base(0x3A)
{
EnsureCapacity(13);
var v = skill.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((byte)0xDF); // type: delta, capped
Stream.Write((ushort)skill.Info.SkillID);
Stream.Write((ushort)uv);
Stream.Write((ushort)skill.BaseFixedPoint);
Stream.Write((byte)skill.Lock);
Stream.Write((ushort)skill.CapFixedPoint);
}
}
public sealed class LaunchBrowser : Packet
{
public LaunchBrowser(string url) : base(0xA5)
{
url ??= "";
EnsureCapacity(4 + url.Length);
Stream.WriteAsciiNull(url);
}
}
public sealed class DragEffect : Packet
{
public DragEffect(IEntity src, IEntity trg, int itemID, int hue, int amount) : base(0x23, 26)
{
Stream.Write((short)itemID);
Stream.Write((byte)0);
Stream.Write((short)hue);
Stream.Write((short)amount);
Stream.Write(src.Serial);
Stream.Write((short)src.X);
Stream.Write((short)src.Y);
Stream.Write((sbyte)src.Z);
Stream.Write(trg.Serial);
Stream.Write((short)trg.X);
Stream.Write((short)trg.Y);
Stream.Write((sbyte)trg.Z);
}
}
public sealed class SeasonChange : Packet
{
private static readonly SeasonChange[][] m_Cache =
{
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2]
};
public SeasonChange(int season, bool playSound = true) : base(0xBC, 3)
{
Stream.Write((byte)season);
Stream.Write(playSound);
}
public static SeasonChange Instantiate(int season) => Instantiate(season, true);
public static SeasonChange Instantiate(int season, bool playSound)
{
if (season >= 0 && season < m_Cache.Length)
{
var idx = playSound ? 1 : 0;
var p = m_Cache[season][idx];
if (p == null)
{
m_Cache[season][idx] = p = new SeasonChange(season, playSound);
p.SetStatic();
}
return p;
}
return new SeasonChange(season, playSound);
}
}
public sealed class DisplayPaperdoll : Packet
{
public DisplayPaperdoll(Serial m, string title, bool warmode, bool canLift) : base(0x88, 66)
{
byte flags = 0x00;
if (warmode)
{
flags |= 0x01;
}
if (canLift)
{
flags |= 0x02;
}
Stream.Write(m);
Stream.WriteAsciiFixed(title, 60);
Stream.Write(flags);
}
}
public sealed class PlayMusic : Packet
{
public static readonly Packet InvalidInstance = SetStatic(new PlayMusic(MusicName.Invalid));
private static readonly Packet[] m_Instances = new Packet[60];
public PlayMusic(MusicName name) : base(0x6D, 3)
{
Stream.Write((short)name);
}
public static Packet GetInstance(MusicName name)
{
if (name == MusicName.Invalid)
{
return InvalidInstance;
}
var v = (int)name;
Packet p;
if (v >= 0 && v < m_Instances.Length)
{
p = m_Instances[v];
if (p == null)
{
m_Instances[v] = p = SetStatic(new PlayMusic(name));
}
}
else
{
p = new PlayMusic(name);
}
return p;
}
}
public sealed class ScrollMessage : Packet
{
public ScrollMessage(int type, int tip, string text) : base(0xA6)
{
text ??= "";
EnsureCapacity(10 + text.Length);
Stream.Write((byte)type);
Stream.Write(tip);
Stream.Write((ushort)text.Length);
Stream.WriteAsciiFixed(text, text.Length);
}
}
public sealed class CurrentTime : Packet
{
public CurrentTime() : this(DateTime.Now)
{
}
public CurrentTime(DateTime date) : base(0x5B, 4)
{
Stream.Write((byte)date.Hour);
Stream.Write((byte)date.Minute);
Stream.Write((byte)date.Second);
}
}
public sealed class PathfindMessage : Packet
{
public PathfindMessage(Point3D p) : base(0x38, 7)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
}
}
public sealed class PingAck : Packet
{
private static readonly PingAck[] m_Cache = new PingAck[0x100];
public PingAck(byte ping) : base(0x73, 2)
{
Stream.Write(ping);
}
public static PingAck Instantiate(byte ping)
{
var p = m_Cache[ping];
if (p == null)
{
m_Cache[ping] = p = new PingAck(ping);
p.SetStatic();
}
return p;
}
}
public sealed class DisplayHuePicker : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
}
Stream.Write((byte)lockBits);
}
}
public sealed class ChangeUpdateRange : Packet
{
private static readonly ChangeUpdateRange[] m_Cache = new ChangeUpdateRange[0x100];
public ChangeUpdateRange(int range) : base(0xC8, 2)
{
Stream.Write((byte)range);
}
public static ChangeUpdateRange Instantiate(int range)
{
var idx = (byte)range;
var p = m_Cache[idx];
if (p == null)
{
m_Cache[idx] = p = new ChangeUpdateRange(range);
p.SetStatic();
}
return p;
}
}
public sealed class DeathStatus : Packet
{
public static readonly Packet Dead = SetStatic(new DeathStatus(true));
public static readonly Packet Alive = SetStatic(new DeathStatus(false));
public DeathStatus(bool dead) : base(0x2C, 2)
{
Stream.Write((byte)(dead ? 0 : 2));
}
public static Packet Instantiate(bool dead) => dead ? Dead : Alive;
}
public sealed class DisplayProfile : Packet
{
public DisplayProfile(Serial m, string header, string body, string footer) : base(0xB8)
{
header ??= "";
body ??= "";
footer ??= "";
EnsureCapacity(12 + header.Length + footer.Length * 2 + body.Length * 2);
Stream.Write(m);
Stream.WriteAsciiNull(header);
Stream.WriteBigUniNull(footer);
Stream.WriteBigUniNull(body);
}
}
public sealed class LiftRej : Packet
{
public LiftRej(LRReason reason) : base(0x27, 2)
{
Stream.Write((byte)reason);
}
}
public sealed class LogoutAck : Packet
{
public LogoutAck() : base(0xD1, 2)
{
Stream.Write((byte)0x01);
}
}
public sealed class Weather : Packet
{
public Weather(int type, int density, int temp) : base(0x65, 4)
{
Stream.Write((byte)type);
Stream.Write((byte)density);
Stream.Write((byte)temp);
}
}
public sealed class ServerChange : Packet
{
public ServerChange(Point3D p, Map map) : base(0x76, 16)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
Stream.Write((byte)0);
Stream.Write((short)0);
Stream.Write((short)0);
Stream.Write((short)map.Width);
Stream.Write((short)map.Height);
}
}
public sealed class SkillUpdate : Packet
{
public SkillUpdate(Skills skills) : base(0x3A)
{
EnsureCapacity(6 + skills.Length * 9);
Stream.Write((byte)0x02); // type: absolute, capped
for (var i = 0; i < skills.Length; ++i)
{
var s = skills[i];
var v = s.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((ushort)(s.Info.SkillID + 1));
Stream.Write((ushort)uv);
Stream.Write((ushort)s.BaseFixedPoint);
Stream.Write((byte)s.Lock);
Stream.Write((ushort)s.CapFixedPoint);
}
Stream.Write((short)0); // terminate
}
}
public sealed class Sequence : Packet
{
public Sequence(int num) : base(0x7B, 2)
{
Stream.Write((byte)num);
}
}
public sealed class SkillChange : Packet
{
public SkillChange(Skill skill) : base(0x3A)
{
EnsureCapacity(13);
var v = skill.NonRacialValue;
var uv = Math.Clamp((int)(v * 10), 0, 0xFFFF);
Stream.Write((byte)0xDF); // type: delta, capped
Stream.Write((ushort)skill.Info.SkillID);
Stream.Write((ushort)uv);
Stream.Write((ushort)skill.BaseFixedPoint);
Stream.Write((byte)skill.Lock);
Stream.Write((ushort)skill.CapFixedPoint);
}
}
public sealed class LaunchBrowser : Packet
{
public LaunchBrowser(string url) : base(0xA5)
{
url ??= "";
EnsureCapacity(4 + url.Length);
Stream.WriteAsciiNull(url);
}
}
public sealed class DragEffect : Packet
{
public DragEffect(IEntity src, IEntity trg, int itemID, int hue, int amount) : base(0x23, 26)
{
Stream.Write((short)itemID);
Stream.Write((byte)0);
Stream.Write((short)hue);
Stream.Write((short)amount);
Stream.Write(src.Serial);
Stream.Write((short)src.X);
Stream.Write((short)src.Y);
Stream.Write((sbyte)src.Z);
Stream.Write(trg.Serial);
Stream.Write((short)trg.X);
Stream.Write((short)trg.Y);
Stream.Write((sbyte)trg.Z);
}
}
public sealed class SeasonChange : Packet
{
private static readonly SeasonChange[][] m_Cache =
{
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2],
new SeasonChange[2]
};
public SeasonChange(int season, bool playSound = true) : base(0xBC, 3)
{
Stream.Write((byte)season);
Stream.Write(playSound);
}
public static SeasonChange Instantiate(int season) => Instantiate(season, true);
public static SeasonChange Instantiate(int season, bool playSound)
{
if (season >= 0 && season < m_Cache.Length)
{
var idx = playSound ? 1 : 0;
var p = m_Cache[season][idx];
if (p == null)
{
m_Cache[season][idx] = p = new SeasonChange(season, playSound);
p.SetStatic();
}
return p;
}
return new SeasonChange(season, playSound);
}
}
public sealed class DisplayPaperdoll : Packet
{
public DisplayPaperdoll(Serial m, string title, bool warmode, bool canLift) : base(0x88, 66)
{
byte flags = 0x00;
if (warmode)
{
flags |= 0x01;
}
if (canLift)
{
flags |= 0x02;
}
Stream.Write(m);
Stream.WriteAsciiFixed(title, 60);
Stream.Write(flags);
}
}
public sealed class PlayMusic : Packet
{
public static readonly Packet InvalidInstance = SetStatic(new PlayMusic(MusicName.Invalid));
private static readonly Packet[] m_Instances = new Packet[60];
public PlayMusic(MusicName name) : base(0x6D, 3)
{
Stream.Write((short)name);
}
public static Packet GetInstance(MusicName name)
{
if (name == MusicName.Invalid)
{
return InvalidInstance;
}
var v = (int)name;
Packet p;
if (v >= 0 && v < m_Instances.Length)
{
p = m_Instances[v];
if (p == null)
{
m_Instances[v] = p = SetStatic(new PlayMusic(name));
}
}
else
{
p = new PlayMusic(name);
}
return p;
}
}
public sealed class ScrollMessage : Packet
{
public ScrollMessage(int type, int tip, string text) : base(0xA6)
{
text ??= "";
EnsureCapacity(10 + text.Length);
Stream.Write((byte)type);
Stream.Write(tip);
Stream.Write((ushort)text.Length);
Stream.WriteAsciiFixed(text, text.Length);
}
}
public sealed class CurrentTime : Packet
{
public CurrentTime() : this(DateTime.Now)
{
}
public CurrentTime(DateTime date) : base(0x5B, 4)
{
Stream.Write((byte)date.Hour);
Stream.Write((byte)date.Minute);
Stream.Write((byte)date.Second);
}
}
public sealed class PathfindMessage : Packet
{
public PathfindMessage(Point3D p) : base(0x38, 7)
{
Stream.Write((short)p.X);
Stream.Write((short)p.Y);
Stream.Write((short)p.Z);
}
}
public sealed class PingAck : Packet
{
private static readonly PingAck[] m_Cache = new PingAck[0x100];
public PingAck(byte ping) : base(0x73, 2)
{
Stream.Write(ping);
}
public static PingAck Instantiate(byte ping)
{
var p = m_Cache[ping];
if (p == null)
{
m_Cache[ping] = p = new PingAck(ping);
p.SetStatic();
}
return p;
}
}
public sealed class DisplayHuePicker : Packet
{
public DisplayHuePicker(HuePicker huePicker) : base(0x95, 9)
{
Stream.Write(huePicker.Serial);
Stream.Write((short)0);
Stream.Write((short)huePicker.ItemID);
}
}

View file

@ -2,114 +2,113 @@ using Server.Items;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
{
[Collection("Sequential Server Tests")]
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class SecureTradePacketTests
{
[Theory]
[InlineData("short-name")]
[InlineData("this is a really long name that is more than 30 characters, probably")]
public void TestDisplaySecureTrade(string name)
{
[Theory]
[InlineData("short-name")]
[InlineData("this is a really long name that is more than 30 characters, probably")]
public void TestDisplaySecureTrade(string name)
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var firstCont = new Container(World.NewItem);
var secondCont = new Container(World.NewItem);
var firstCont = new Container(World.NewItem);
var secondCont = new Container(World.NewItem);
var expected = new DisplaySecureTrade(m, firstCont, secondCont, name).Compile();
var expected = new DisplaySecureTrade(m, firstCont, secondCont, name).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplaySecureTrade(m, firstCont, secondCont, name);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplaySecureTrade(m, firstCont, secondCont, name);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestCloseSecureTrade()
{
var cont = new Container(World.NewItem);
[Fact]
public void TestCloseSecureTrade()
{
var cont = new Container(World.NewItem);
var expected = new CloseSecureTrade(cont).Compile();
var expected = new CloseSecureTrade(cont).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCloseSecureTrade(cont);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCloseSecureTrade(cont);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory, InlineData(true, false), InlineData(false, true)]
// Update first
// Update second
public void TestUpdateSecureTrade(bool first, bool second)
{
var firstCont = new Container(World.NewItem);
var secondCont = new Container(World.NewItem);
[Theory, InlineData(true, false), InlineData(false, true)]
// Update first
// Update second
public void TestUpdateSecureTrade(bool first, bool second)
{
var firstCont = new Container(World.NewItem);
var secondCont = new Container(World.NewItem);
var cont = first ? firstCont : secondCont;
var expected = new UpdateSecureTrade(cont, first, second).Compile();
var cont = first ? firstCont : secondCont;
var expected = new UpdateSecureTrade(cont, first, second).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendUpdateSecureTrade(cont, first, second);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendUpdateSecureTrade(cont, first, second);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(100000, 30, TradeFlag.UpdateGold)]
[InlineData(250000, 50000, TradeFlag.UpdateLedger)]
public void TestUpdateGoldSecureTrade(int gold, int plat, TradeFlag flag)
{
var cont = new Container(World.NewItem);
var expected = new UpdateSecureTrade(cont, flag, gold, plat).Compile();
[Theory]
[InlineData(100000, 30, TradeFlag.UpdateGold)]
[InlineData(250000, 50000, TradeFlag.UpdateLedger)]
public void TestUpdateGoldSecureTrade(int gold, int plat, TradeFlag flag)
{
var cont = new Container(World.NewItem);
var expected = new UpdateSecureTrade(cont, flag, gold, plat).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendUpdateSecureTrade(cont, flag, gold, plat);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendUpdateSecureTrade(cont, flag, gold, plat);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestSecureTradeEquip()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
[Fact]
public void TestSecureTradeEquip()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var cont = new Container(World.NewItem);
var itemInCont = new Item(World.NewItem) { Parent = cont };
var cont = new Container(World.NewItem);
var itemInCont = new Item(World.NewItem) { Parent = cont };
var expected = new SecureTradeEquip(itemInCont, m).Compile();
var expected = new SecureTradeEquip(itemInCont, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSecureTradeEquip(itemInCont, m);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSecureTradeEquip(itemInCont, m);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestSecureTradeEquip6017()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
[Fact]
public void TestSecureTradeEquip6017()
{
var m = new Mobile((Serial)0x1);
m.DefaultMobileInit();
var cont = new Container(World.NewItem);
var itemInCont = new Item(World.NewItem) { Parent = cont };
var cont = new Container(World.NewItem);
var itemInCont = new Item(World.NewItem) { Parent = cont };
var expected = new SecureTradeEquip6017(itemInCont, m).Compile();
var expected = new SecureTradeEquip6017(itemInCont, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.ContainerGridLines;
ns.SendSecureTradeEquip(itemInCont, m);
ns.SendSecureTradeEquip(itemInCont, m);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,89 +1,88 @@
using Server.Items;
namespace Server.Network
namespace Server.Network;
public sealed class DisplaySecureTrade : Packet
{
public sealed class DisplaySecureTrade : Packet
public DisplaySecureTrade(Mobile them, Container first, Container second, string name)
: base(0x6F)
{
public DisplaySecureTrade(Mobile them, Container first, Container second, string name)
: base(0x6F)
{
name ??= "";
name ??= "";
EnsureCapacity(17 + name.Length);
EnsureCapacity(17 + name.Length);
Stream.Write((byte)0); // Display
Stream.Write(them.Serial);
Stream.Write(first.Serial);
Stream.Write(second.Serial);
Stream.Write(true);
Stream.Write((byte)0); // Display
Stream.Write(them.Serial);
Stream.Write(first.Serial);
Stream.Write(second.Serial);
Stream.Write(true);
Stream.WriteAsciiFixed(name, 30);
}
}
public sealed class CloseSecureTrade : Packet
{
public CloseSecureTrade(Container cont)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)1); // Close
Stream.Write(cont.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write(false);
}
}
public sealed class UpdateSecureTrade : Packet
{
public UpdateSecureTrade(Container cont, bool first, bool second)
: this(cont, TradeFlag.Update, first ? 1 : 0, second ? 1 : 0)
{
}
public UpdateSecureTrade(Container cont, TradeFlag flag, int first, int second)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)flag);
Stream.Write(cont.Serial);
Stream.Write(first);
Stream.Write(second);
Stream.Write(false);
}
}
public sealed class SecureTradeEquip : Packet
{
public SecureTradeEquip(Item item, Mobile m) : base(0x25, 20)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
public sealed class SecureTradeEquip6017 : Packet
{
public SecureTradeEquip6017(Item item, Mobile m) : base(0x25, 21)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
Stream.WriteAsciiFixed(name, 30);
}
}
public sealed class CloseSecureTrade : Packet
{
public CloseSecureTrade(Container cont)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)1); // Close
Stream.Write(cont.Serial);
Stream.Write(0);
Stream.Write(0);
Stream.Write(false);
}
}
public sealed class UpdateSecureTrade : Packet
{
public UpdateSecureTrade(Container cont, bool first, bool second)
: this(cont, TradeFlag.Update, first ? 1 : 0, second ? 1 : 0)
{
}
public UpdateSecureTrade(Container cont, TradeFlag flag, int first, int second)
: base(0x6F)
{
EnsureCapacity(17);
Stream.Write((byte)flag);
Stream.Write(cont.Serial);
Stream.Write(first);
Stream.Write(second);
Stream.Write(false);
}
}
public sealed class SecureTradeEquip : Packet
{
public SecureTradeEquip(Item item, Mobile m) : base(0x25, 20)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}
public sealed class SecureTradeEquip6017 : Packet
{
public SecureTradeEquip6017(Item item, Mobile m) : base(0x25, 21)
{
Stream.Write(item.Serial);
Stream.Write((short)item.ItemID);
Stream.Write((byte)0);
Stream.Write((short)item.Amount);
Stream.Write((short)item.X);
Stream.Write((short)item.Y);
Stream.Write((byte)0); // Grid Location?
Stream.Write(m.Serial);
Stream.Write((short)item.Hue);
}
}

View file

@ -1,67 +1,66 @@
using System.IO;
using Server.Targeting;
namespace Server.Network
namespace Server.Network;
public sealed class MultiTargetReqHS : Packet
{
public sealed class MultiTargetReqHS : Packet
public MultiTargetReqHS(MultiTarget t) : base(0x99, 30)
{
public MultiTargetReqHS(MultiTarget t) : base(0x99, 30)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
// DWORD Hue
}
}
public sealed class MultiTargetReq : Packet
{
public MultiTargetReq(MultiTarget t) : base(0x99, 26)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
}
}
public sealed class CancelTarget : Packet
{
public static readonly Packet Instance = SetStatic(new CancelTarget());
public CancelTarget() : base(0x6C, 19)
{
Stream.Write((byte)0);
Stream.Write(0);
Stream.Write((byte)3);
Stream.Fill();
}
}
public sealed class TargetReq : Packet
{
public TargetReq(Target t) : base(0x6C, 19)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
}
// DWORD Hue
}
}
public sealed class MultiTargetReq : Packet
{
public MultiTargetReq(MultiTarget t) : base(0x99, 26)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
Stream.Seek(18, SeekOrigin.Begin);
Stream.Write((short)t.MultiID);
Stream.Write((short)t.Offset.X);
Stream.Write((short)t.Offset.Y);
Stream.Write((short)t.Offset.Z);
}
}
public sealed class CancelTarget : Packet
{
public static readonly Packet Instance = SetStatic(new CancelTarget());
public CancelTarget() : base(0x6C, 19)
{
Stream.Write((byte)0);
Stream.Write(0);
Stream.Write((byte)3);
Stream.Fill();
}
}
public sealed class TargetReq : Packet
{
public TargetReq(Target t) : base(0x6C, 19)
{
Stream.Write(t.AllowGround);
Stream.Write(t.TargetID);
Stream.Write((byte)t.Flags);
Stream.Fill();
}
}

View file

@ -2,89 +2,89 @@ using Server.Network;
using Server.Targeting;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
public class TestMultiTarget : MultiTarget
{
public class TestMultiTarget : MultiTarget
public TestMultiTarget(
int multiID,
Point3D offset,
int range = 10,
bool allowGround = true,
TargetFlags flags = TargetFlags.None
) : base(multiID, offset, range, allowGround, flags)
{
public TestMultiTarget(
int multiID,
Point3D offset,
int range = 10,
bool allowGround = true,
TargetFlags flags = TargetFlags.None
) : base(multiID, offset, range, allowGround, flags)
{
}
}
public class TestTarget : Target
{
public TestTarget(
int range,
bool allowGround,
TargetFlags flags
) : base(range, allowGround, flags)
{
}
}
public class TargetPacketsTests
{
[Fact]
public void TestMultiTargetReqHS()
{
var multiID = 0x1024;
var p = new Point3D(1000, 100, 10);
MultiTarget t = new TestMultiTarget(multiID, p);
var expected = new MultiTargetReqHS(t).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.HighSeas;
ns.SendMultiTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMultiTargetReq()
{
var multiID = 0x1024;
var p = new Point3D(1000, 100, 10);
MultiTarget t = new TestMultiTarget(multiID, p);
var expected = new MultiTargetReq(t).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMultiTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestCancelTarget()
{
var expected = new CancelTarget().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCancelTarget();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestTargetReq()
{
var t = new TestTarget(10, true, TargetFlags.Beneficial);
var expected = new TargetReq(t).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}
}
public class TestTarget : Target
{
public TestTarget(
int range,
bool allowGround,
TargetFlags flags
) : base(range, allowGround, flags)
{
}
}
[Collection("Sequential Server Tests")]
public class TargetPacketsTests
{
[Fact]
public void TestMultiTargetReqHS()
{
var multiID = 0x1024;
var p = new Point3D(1000, 100, 10);
MultiTarget t = new TestMultiTarget(multiID, p);
var expected = new MultiTargetReqHS(t).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges |= ProtocolChanges.HighSeas;
ns.SendMultiTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestMultiTargetReq()
{
var multiID = 0x1024;
var p = new Point3D(1000, 100, 10);
MultiTarget t = new TestMultiTarget(multiID, p);
var expected = new MultiTargetReq(t).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMultiTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestCancelTarget()
{
var expected = new CancelTarget().Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCancelTarget();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestTargetReq()
{
var t = new TestTarget(10, true, TargetFlags.Beneficial);
var expected = new TargetReq(t).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendTargetReq(t);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -3,92 +3,91 @@ using Server.Items;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class VendorBuyPacketTests
{
[Collection("Sequential Server Tests")]
public class VendorBuyPacketTests
[Theory]
[InlineData(ProtocolChanges.None)]
[InlineData(ProtocolChanges.ContainerGridLines)]
public void TestVendorBuyContent(ProtocolChanges protocolChanges)
{
[Theory]
[InlineData(ProtocolChanges.None)]
[InlineData(ProtocolChanges.ContainerGridLines)]
public void TestVendorBuyContent(ProtocolChanges protocolChanges)
var cont = new Container(World.NewItem);
var buyStates = new List<BuyItemState>
{
var cont = new Container(World.NewItem);
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 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)
};
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = protocolChanges;
var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = protocolChanges;
var expected = new VendorBuyContent(buyStates, ns.ContainerGridLines).Compile();
var expected = new VendorBuyContent(buyStates, ns.ContainerGridLines).Compile();
ns.SendVendorBuyContent(buyStates);
ns.SendVendorBuyContent(buyStates);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Theory]
[InlineData(ProtocolChanges.None)]
[InlineData(ProtocolChanges.HighSeas)]
public void TestDisplayBuyList(ProtocolChanges protocolChanges)
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
[Theory]
[InlineData(ProtocolChanges.None)]
[InlineData(ProtocolChanges.HighSeas)]
public void TestDisplayBuyList(ProtocolChanges protocolChanges)
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = protocolChanges;
var expected = new DisplayBuyList(vendor.Serial, ns.HighSeas).Compile();
ns.SendDisplayBuyList(vendor.Serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestVendorBuyList()
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
var cont = new Container(World.NewItem);
var buyStates = new List<BuyItemState>
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
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 ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = protocolChanges;
var expected = new VendorBuyList(vendor, buyStates).Compile();
var expected = new DisplayBuyList(vendor.Serial, ns.HighSeas).Compile();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendVendorBuyList(vendor, buyStates);
ns.SendDisplayBuyList(vendor.Serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestEndVendorBuy()
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
[Fact]
public void TestVendorBuyList()
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
var expected = new EndVendorBuy(vendor.Serial).Compile();
var cont = new Container(World.NewItem);
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEndVendorBuy(vendor.Serial);
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 expected = new VendorBuyList(vendor, buyStates).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendVendorBuyList(vendor, buyStates);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
[Fact]
public void TestEndVendorBuy()
{
var vendor = new Mobile((Serial)0x1);
vendor.DefaultMobileInit();
var expected = new EndVendorBuy(vendor.Serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEndVendorBuy(vendor.Serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -1,80 +1,79 @@
using System.Collections.Generic;
using Server.Items;
namespace Server.Network
namespace Server.Network;
public sealed class VendorBuyContent : Packet
{
public sealed class VendorBuyContent : Packet
public VendorBuyContent(List<BuyItemState> list, bool containerGridLines) : base(0x3C)
{
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)
{
EnsureCapacity(list.Count * 19 + 5);
var bis = list[i];
Stream.Write((short)list.Count);
for (var i = list.Count - 1; i >= 0; --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)
{
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);
Stream.Write((byte)0); // Grid Location?
}
}
}
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 not 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 + 1));
Stream.WriteAsciiNull(desc);
}
}
}
public sealed class EndVendorBuy : Packet
{
public EndVendorBuy(Serial vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor);
Stream.Write((byte)0);
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 not 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 + 1));
Stream.WriteAsciiNull(desc);
}
}
}
public sealed class EndVendorBuy : Packet
{
public EndVendorBuy(Serial vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor);
Stream.Write((byte)0);
}
}

View file

@ -3,50 +3,49 @@ using System.Linq;
using Server.Network;
using Xunit;
namespace Server.Tests.Network
namespace Server.Tests.Network;
[Collection("Sequential Server Tests")]
public class VendorSellPacketTests
{
[Collection("Sequential Server Tests")]
public class VendorSellPacketTests
[Fact]
public void TestVendorSellList()
{
[Fact]
public void TestVendorSellList()
var vendor = new Mobile((Serial)0x1024u);
vendor.DefaultMobileInit();
var item1 = new Item(World.NewItem);
var item2 = new Item(World.NewItem) { Name = "Second Item" };
var item3 = new Item(World.NewItem);
var sellStates = new HashSet<SellItemState>
{
var vendor = new Mobile((Serial)0x1024u);
vendor.DefaultMobileInit();
new(item1, 100, "Item 1"),
new(item2, 100000, "Item 2"),
new(item3, 1, "Item 3")
};
var item1 = new Item(World.NewItem);
var item2 = new Item(World.NewItem) { Name = "Second Item" };
var item3 = new Item(World.NewItem);
var expected = new VendorSellList(vendor, sellStates.ToList()).Compile();
var sellStates = new HashSet<SellItemState>
{
new(item1, 100, "Item 1"),
new(item2, 100000, "Item 2"),
new(item3, 1, "Item 3")
};
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendVendorSellList(vendor.Serial, sellStates);
var expected = new VendorSellList(vendor, sellStates.ToList()).Compile();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendVendorSellList(vendor.Serial, sellStates);
[Fact]
public void TestEndVendorSell()
{
var vendor = new Mobile((Serial)0x1024u);
vendor.DefaultMobileInit();
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var expected = new EndVendorBuy(vendor.Serial).Compile();
[Fact]
public void TestEndVendorSell()
{
var vendor = new Mobile((Serial)0x1024u);
vendor.DefaultMobileInit();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEndVendorSell(vendor.Serial);
var expected = new EndVendorBuy(vendor.Serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEndVendorSell(vendor.Serial);
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
var result = ns.SendPipe.Reader.AvailableToRead();
AssertThat.Equal(result, expected);
}
}

View file

@ -15,41 +15,40 @@
using System.Collections.Generic;
namespace Server.Network
namespace Server.Network;
public sealed class VendorSellList : Packet
{
public sealed class VendorSellList : Packet
public VendorSellList(Mobile shopkeeper, List<SellItemState> sis) : base(0x9E)
{
public VendorSellList(Mobile shopkeeper, List<SellItemState> sis) : base(0x9E)
EnsureCapacity(256);
Stream.Write(shopkeeper.Serial);
Stream.Write((ushort)sis.Count);
foreach (var state in sis)
{
EnsureCapacity(256);
Stream.Write(state.Item.Serial);
Stream.Write((ushort)state.Item.ItemID);
Stream.Write((ushort)state.Item.Hue);
Stream.Write((ushort)state.Item.Amount);
Stream.Write((ushort)state.Price);
Stream.Write(shopkeeper.Serial);
var name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim();
Stream.Write((ushort)sis.Count);
foreach (var state in sis)
{
Stream.Write(state.Item.Serial);
Stream.Write((ushort)state.Item.ItemID);
Stream.Write((ushort)state.Item.Hue);
Stream.Write((ushort)state.Item.Amount);
Stream.Write((ushort)state.Price);
var name = string.IsNullOrWhiteSpace(state.Item.Name) ? state.Name ?? "" : state.Item.Name.Trim();
Stream.Write((ushort)name.Length);
Stream.WriteAsciiFixed(name, (ushort)name.Length);
}
}
}
public sealed class EndVendorSell : Packet
{
public EndVendorSell(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
Stream.Write((ushort)name.Length);
Stream.WriteAsciiFixed(name, (ushort)name.Length);
}
}
}
public sealed class EndVendorSell : Packet
{
public EndVendorSell(Mobile vendor) : base(0x3B, 8)
{
Stream.Write((ushort)8); // length
Stream.Write(vendor.Serial);
Stream.Write((byte)0);
}
}

View file

@ -17,7 +17,7 @@ public class VirtualHairPacketTests
var expected = new HairEquipUpdate(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendHairEquipUpdatePacket(m, (uint)m.Hair.VirtualSerial, m.Hair.ItemId, m.Hair.Hue, Layer.Hair);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -32,7 +32,7 @@ public class VirtualHairPacketTests
var expected = new RemoveHair(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRemoveHairPacket((uint) m.Hair.VirtualSerial);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -1,52 +1,51 @@
namespace Server.Network
namespace Server.Network;
public sealed class HairEquipUpdate : Packet
{
public sealed class HairEquipUpdate : Packet
public HairEquipUpdate(Mobile parent)
: base(0x2E, 15)
{
public HairEquipUpdate(Mobile parent)
: base(0x2E, 15)
{
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.HairHue;
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.HairHue;
Stream.Write(parent.Hair.VirtualSerial);
Stream.Write((short)parent.HairItemID);
Stream.Write((byte)0);
Stream.Write((byte)Layer.Hair);
Stream.Write(parent.Serial);
Stream.Write((short)hue);
}
}
public sealed class FacialHairEquipUpdate : Packet
{
public FacialHairEquipUpdate(Mobile parent)
: base(0x2E, 15)
{
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.FacialHairHue;
Stream.Write(parent.FacialHair.VirtualSerial);
Stream.Write((short)parent.FacialHairItemID);
Stream.Write((byte)0);
Stream.Write((byte)Layer.FacialHair);
Stream.Write(parent.Serial);
Stream.Write((short)hue);
}
}
public sealed class RemoveHair : Packet
{
public RemoveHair(Mobile parent)
: base(0x1D, 5)
{
Stream.Write(parent.Hair.VirtualSerial);
}
}
public sealed class RemoveFacialHair : Packet
{
public RemoveFacialHair(Mobile parent)
: base(0x1D, 5)
{
Stream.Write(parent.FacialHair.VirtualSerial);
}
Stream.Write(parent.Hair.VirtualSerial);
Stream.Write((short)parent.HairItemID);
Stream.Write((byte)0);
Stream.Write((byte)Layer.Hair);
Stream.Write(parent.Serial);
Stream.Write((short)hue);
}
}
public sealed class FacialHairEquipUpdate : Packet
{
public FacialHairEquipUpdate(Mobile parent)
: base(0x2E, 15)
{
var hue = parent.SolidHueOverride >= 0 ? parent.SolidHueOverride : parent.FacialHairHue;
Stream.Write(parent.FacialHair.VirtualSerial);
Stream.Write((short)parent.FacialHairItemID);
Stream.Write((byte)0);
Stream.Write((byte)Layer.FacialHair);
Stream.Write(parent.Serial);
Stream.Write((short)hue);
}
}
public sealed class RemoveHair : Packet
{
public RemoveHair(Mobile parent)
: base(0x1D, 5)
{
Stream.Write(parent.Hair.VirtualSerial);
}
}
public sealed class RemoveFacialHair : Packet
{
public RemoveFacialHair(Mobile parent)
: base(0x1D, 5)
{
Stream.Write(parent.FacialHair.VirtualSerial);
}
}

View file

@ -56,6 +56,12 @@ public class IPRateLimiter
public bool Verify(IPAddress ip, out int totalAttempts)
{
if (ip.IsPrivateNetwork())
{
totalAttempts = 0;
return true;
}
var nowTicks = Core.TickCount;
var ipStats = _ipAttempts.GetOrAdd(ip, _ => GetOrCreateIPStats());
var added = ipStats.AttemptCount == 0;

View file

@ -35,7 +35,7 @@ namespace Server.Network;
public delegate void DecodePacket(Span<byte> buffer, ref int length);
public delegate int EncodePacket(ReadOnlySpan<byte> inputBuffer, Span<byte> outputBuffer);
public partial class NetState : IComparable<NetState>, IValueLinkListNode<NetState>
public partial class NetState : IComparable<NetState>, IValueLinkListNode<NetState>, IDisposable
{
private static readonly ILogger logger = LogFactory.GetLogger(typeof(NetState));
@ -1142,8 +1142,11 @@ public partial class NetState : IComparable<NetState>, IValueLinkListNode<NetSta
}
}
private void Dispose()
// Do not run this directly. Use Disconnect instead.
// This is available for testing cleanup only.
public void Dispose()
{
_running = false;
// It's possible we could queue for dispose multiple times
if (Connection == null)
{

View file

@ -0,0 +1,49 @@
using System.Net;
using System.Net.Sockets;
using Server.Network;
namespace Server;
public static class NetworkUtilities
{
public static bool IsPrivateNetwork(this IPAddress ip) =>
ip.AddressFamily switch
{
AddressFamily.InterNetwork => ip.IsPrivateNetworkV4(),
AddressFamily.InterNetworkV6 => ip.IsPrivateNetworkV6(),
_ => false
};
private static readonly IFirewallEntry[] _privateNetworkV4 =
[
new CidrFirewallEntry("127.0.0.1/8"),
new CidrFirewallEntry("192.168.0.0/16"),
new CidrFirewallEntry("10.0.0.0/8"),
new CidrFirewallEntry("172.16.0.0/12"),
new CidrFirewallEntry("169.254.0.0/16"),
new CidrFirewallEntry("100.64.0.0/10")
];
private static readonly IFirewallEntry[] _privateNetworkV6 =
[
new CidrFirewallEntry("fc00::/7"),
new CidrFirewallEntry("fe80::/10")
];
public static bool IsPrivateNetworkV4(this IPAddress ip)
{
for (var i = 0; i < _privateNetworkV4.Length; i++)
{
if (_privateNetworkV4[i].IsBlocked(ip))
{
return true;
}
}
return false;
}
public static bool IsPrivateNetworkV6(this IPAddress ip) =>
_privateNetworkV6[0].IsBlocked(ip) ||
_privateNetworkV6[1].IsBlocked(ip);
}

View file

@ -2,6 +2,7 @@ using System;
using System.Reflection;
using Server.Items;
using Server.Misc;
using Server.Tests.Maps;
using Xunit;
namespace Server.Tests;

View file

@ -5,6 +5,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential Server Tests")]
public class ChatPacketTests
{
[Theory]
@ -14,7 +15,7 @@ public class ChatPacketTests
{
var expected = new ChatMessagePacket(lang, number, param1, param2).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendChatMessage(lang, number, param1, param2);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -6,6 +6,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential UOContent Tests")]
public class TestHelpTopicPacket
{
[Theory]
@ -15,7 +16,7 @@ public class TestHelpTopicPacket
{
var expected = new DisplayHelpTopic(topic, display).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDisplayHelpTopic(topic, display);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -5,6 +5,7 @@ using Xunit;
namespace Server.Engines.MLQuests;
[Collection("Sequential UOContent Tests")]
public class MLQuestPacketTests
{
private class MockedRace : Race
@ -69,7 +70,7 @@ public class MLQuestPacketTests
var expected = new RaceChanger(female, race).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRaceChanger(female, race);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -81,7 +82,7 @@ public class MLQuestPacketTests
{
var expected = new CloseRaceChanger().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCloseRaceChanger();
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -16,7 +16,7 @@ public class PartyPacketTests
var expected = new PartyEmptyList(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPartyRemoveMember(m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -37,7 +37,7 @@ public class PartyPacketTests
var expected = new PartyRemoveMember(member.Serial, p).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPartyRemoveMember(member.Serial, p);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -58,7 +58,7 @@ public class PartyPacketTests
var expected = new PartyMemberList(p).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPartyMemberList(p);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -75,7 +75,7 @@ public class PartyPacketTests
var expected = new PartyTextMessage(toAll, serial, text).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPartyTextMessage(serial, text, toAll);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -89,7 +89,7 @@ public class PartyPacketTests
var expected = new PartyInvitation(m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendPartyInvitation(m);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -7,6 +7,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential Server Tests")]
public class CharacterStatuePacketTests
{
[Theory]
@ -15,7 +16,7 @@ public class CharacterStatuePacketTests
{
var expected = new UpdateStatueAnimation((Serial)s, status, anim, frame).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendStatueAnimation((Serial)s, status, anim, frame);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -47,7 +47,7 @@ public class BookPacketTests
var expected = new BookHeader(m, book).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBookCover(m, book);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -84,7 +84,7 @@ public class BookPacketTests
var expected = new BookPageDetails(book).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBookContent(book);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -20,7 +20,7 @@ public class BulletinBoardPacketTests
var expected = new BBDisplayBoard(bb).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBBDisplayBoard(bb);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -47,7 +47,7 @@ public class BulletinBoardPacketTests
var expected = (content ?
(Packet)new BBMessageContent(bb, msg) : new BBMessageHeader(bb, msg)).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBBMessage(bb, msg, content);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -16,7 +16,7 @@ public class MahjongPacketTests
var expected = new MahjongJoinGame(game).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongJoinGame(game);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -36,7 +36,7 @@ public class MahjongPacketTests
var expected = new MahjongPlayersInfo(game, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongPlayersInfo(game, m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -54,7 +54,7 @@ public class MahjongPacketTests
var expected = new MahjongGeneralInfo(game).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongGeneralInfo(game);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -74,7 +74,7 @@ public class MahjongPacketTests
var expected = new MahjongTilesInfo(game, m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongTilesInfo(game, m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -94,7 +94,7 @@ public class MahjongPacketTests
var expected = new MahjongTileInfo(game.Tiles[0], m).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongTileInfo(game.Tiles[0], m);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -108,7 +108,7 @@ public class MahjongPacketTests
var expected = new MahjongRelieve(game).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMahjongRelieve(game);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -17,7 +17,7 @@ public class TestMapItemPackets
{
var mapItem = new MapItem(Map.Trammel);
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
var expected = (ns.NewCharacterList ?
@ -39,7 +39,7 @@ public class TestMapItemPackets
var expected = new MapCommand(mapItem, command, number, x, y).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendMapCommand(mapItem, command, x, y, number > 0);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -23,7 +23,7 @@ public class CorpsePacketTests
var expected = new CorpseEquip(m, c).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCorpseEquip(m, c);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -43,7 +43,7 @@ public class CorpsePacketTests
var c = new Corpse(m, m.Items);
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = changes;
var expected = (ns.ContainerGridLines ? (Packet)new CorpseContent6017(m, c) : new CorpseContent(m, c)).Compile();

View file

@ -5,6 +5,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential UOContent Tests")]
public class WeaponAbilityPacketTests
{
[Theory]
@ -16,7 +17,7 @@ public class WeaponAbilityPacketTests
{
var expected = new ToggleSpecialAbility(abilityId, active).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendToggleSpecialAbility(abilityId, active);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -28,7 +29,7 @@ public class WeaponAbilityPacketTests
{
var expected = new ClearWeaponAbility().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendClearWeaponAbility();
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -53,7 +53,7 @@ public class BoatPacketTests
beholder.CanSeeEntities.Add(boat);
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.HighSeas;
var expected = new MoveBoatHS(beholder, boat, d, speed, list, xOffset, yOffset).Compile();
@ -96,7 +96,7 @@ public class BoatPacketTests
beholder.CanSeeEntities.Add(boat);
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.HighSeas;
var expected = new DisplayBoatHS(beholder, boat).Compile();

View file

@ -8,6 +8,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential UOContent Tests")]
public class HousePacketTests
{
[Theory]
@ -16,7 +17,7 @@ public class HousePacketTests
{
var expected = new BeginHouseCustomization((Serial)serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendBeginHouseCustomization((Serial)serial);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -29,7 +30,7 @@ public class HousePacketTests
{
var expected = new EndHouseCustomization((Serial)serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendEndHouseCustomization((Serial)serial);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -43,7 +44,7 @@ public class HousePacketTests
{
var expected = new DesignStateGeneral((Serial)serial, revision).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendDesignStateGeneral((Serial)serial, revision);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -3,6 +3,7 @@ using Xunit;
namespace Server.Tests.Network;
[Collection("Sequential UOContent Tests")]
public class ArrowPacketTests
{
[Fact]
@ -10,7 +11,7 @@ public class ArrowPacketTests
{
var expected = new CancelArrow().Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendCancelArrow(0, 0, Serial.Zero);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -25,7 +26,7 @@ public class ArrowPacketTests
{
var expected = new SetArrow(x, y).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSetArrow(x, y, Serial.Zero);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -42,7 +43,7 @@ public class ArrowPacketTests
var expected = new CancelArrowHS(x, y, serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.HighSeas;
ns.SendCancelArrow(x, y, serial);
@ -60,7 +61,7 @@ public class ArrowPacketTests
var expected = new SetArrowHS(x, y, serial).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.ProtocolChanges = ProtocolChanges.HighSeas;
ns.SendSetArrow(x, y, serial);

View file

@ -8,6 +8,7 @@ using Xunit;
namespace UOContent.Tests;
[Collection("Sequential UOContent Tests")]
public class BuffIconPacketTests
{
[Theory]
@ -20,7 +21,7 @@ public class BuffIconPacketTests
(Serial)mob, iconID, titleCliloc, secondaryCliloc, args, timeSpan
).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendAddBuffPacket((Serial)mob, iconID, titleCliloc, secondaryCliloc, args, (int)timeSpan.TotalMilliseconds);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -34,7 +35,7 @@ public class BuffIconPacketTests
var buffIcon = BuffIcon.Disguised;
var expected = new RemoveBuffPacket(m, buffIcon).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendRemoveBuffPacket(m, buffIcon);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -24,7 +24,7 @@ public class SkillPacketsTests
var expected = new SkillChange(skill).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSkillChange(skill);
var result = ns.SendPipe.Reader.AvailableToRead();
@ -42,7 +42,7 @@ public class SkillPacketsTests
var expected = new SkillUpdate(skills).Compile();
var ns = PacketTestUtilities.CreateTestNetState();
using var ns = PacketTestUtilities.CreateTestNetState();
ns.SendSkillsUpdate(skills);
var result = ns.SendPipe.Reader.AvailableToRead();

View file

@ -92,11 +92,11 @@ namespace Server.Misc
{
localAddress = _publicAddress;
}
else if (IsPrivateNetwork(localAddress))
else if (localAddress.IsPrivateNetwork())
{
ipep = (IPEndPoint)ns.Connection.RemoteEndPoint;
if (ipep == null || !IsPrivateNetwork(ipep.Address) && _publicAddress != null)
if (ipep == null || !ipep.Address.IsPrivateNetwork() && _publicAddress != null)
{
localAddress = _publicAddress;
}
@ -158,7 +158,7 @@ namespace Server.Misc
{
var ip = unicast.Address;
if (!IPAddress.IsLoopback(ip) && ip.AddressFamily != AddressFamily.InterNetworkV6 &&
!IsPrivateNetwork(ip))
!ip.IsPrivateNetwork())
{
return true;
}
@ -168,40 +168,6 @@ namespace Server.Misc
return false;
}
private static bool IsPrivateNetwork(IPAddress ip) =>
ip.AddressFamily switch
{
AddressFamily.InterNetwork => IsPrivateNetworkV4(ip),
AddressFamily.InterNetworkV6 => IsPrivateNetworkV6(ip),
_ => false
};
private static readonly IFirewallEntry[] _privateNetworkV4 =
[
new CidrFirewallEntry("192.168.0.0/16"),
new CidrFirewallEntry("10.0.0.0/8"),
new CidrFirewallEntry("172.16.0.0/12"),
new CidrFirewallEntry("169.254.0.0/16"),
new CidrFirewallEntry("100.64.0.0/10")
];
private static readonly IFirewallEntry[] _privateNetworkV6 =
[
new CidrFirewallEntry("fc00::/7"),
new CidrFirewallEntry("fe80::/10")
];
private static bool IsPrivateNetworkV4(IPAddress ip) =>
_privateNetworkV4[0].IsBlocked(ip) ||
_privateNetworkV4[1].IsBlocked(ip) ||
_privateNetworkV4[2].IsBlocked(ip) ||
_privateNetworkV4[3].IsBlocked(ip) ||
_privateNetworkV4[4].IsBlocked(ip);
private static bool IsPrivateNetworkV6(IPAddress ip) =>
_privateNetworkV6[0].IsBlocked(ip) ||
_privateNetworkV6[1].IsBlocked(ip);
private const string _ipifyUrl = "https://api.ipify.org";
private static IPAddress FindPublicAddress()