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:
parent
8133983b64
commit
1e4c32c809
77 changed files with 4612 additions and 4616 deletions
|
|
@ -1,4 +1,4 @@
|
|||
namespace Server.Tests;
|
||||
namespace Server.Tests.Maps;
|
||||
|
||||
public static class TestMapDefinitions
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ using System.IO;
|
|||
using System.Reflection;
|
||||
using System.Threading;
|
||||
using Server.Items;
|
||||
using Server.Tests.Maps;
|
||||
|
||||
namespace Server.Tests;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Buffers;
|
|||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests;
|
||||
namespace Server.Tests.Buffers;
|
||||
|
||||
public class SpanReaderTests
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ using System.Buffers;
|
|||
using System.IO;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests;
|
||||
namespace Server.Tests.Buffers;
|
||||
|
||||
public class SpanWriterTests
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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).
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
49
Projects/Server/Utilities/NetworkUtilities.cs
Normal file
49
Projects/Server/Utilities/NetworkUtilities.cs
Normal 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);
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Reflection;
|
||||
using Server.Items;
|
||||
using Server.Misc;
|
||||
using Server.Tests.Maps;
|
||||
using Xunit;
|
||||
|
||||
namespace Server.Tests;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue