diff --git a/documentation/DocumentationTest.PacketsDocumentation.verified.md b/documentation/DocumentationTest.PacketsDocumentation.verified.md index 167c6d22..4f224bd4 100644 --- a/documentation/DocumentationTest.PacketsDocumentation.verified.md +++ b/documentation/DocumentationTest.PacketsDocumentation.verified.md @@ -75,7 +75,7 @@ - [treq](../src/NosCore.Packets/ClientPackets/Event/TreqPacket.cs) *InGame* ### Exchanges -- [req_exc](../src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs) *InGame* +- [req_exc](../src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs) *InTrade | InGame* - [exc_list](../src/NosCore.Packets/ClientPackets/Exchanges/ExcListPacket.cs) *InTrade | InGame* ### Families diff --git a/src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs b/src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs index 1d75cc97..675e3d61 100644 --- a/src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs +++ b/src/NosCore.Packets/ClientPackets/Exchanges/ExchangeRequestPacket.cs @@ -10,7 +10,7 @@ namespace NosCore.Packets.ClientPackets.Exchanges { - [PacketHeader("req_exc", Scope.InGame)] + [PacketHeader("req_exc", Scope.InGame | Scope.InTrade)] public class ExchangeRequestPacket : PacketBase { [PacketIndex(0)] diff --git a/src/NosCore.Packets/Deserializer.cs b/src/NosCore.Packets/Deserializer.cs index 06e652b0..8ef6b6a0 100644 --- a/src/NosCore.Packets/Deserializer.cs +++ b/src/NosCore.Packets/Deserializer.cs @@ -346,7 +346,15 @@ public IPacket Deserialize(string packetContent) } if (isMaxIndex && string.IsNullOrWhiteSpace(separator)) { - length = (sbyte)(matches.Length - currentIndex); + var remainingTokens = matches.Length - currentIndex; + // Sub-packets whose fields are space-separated span several tokens each + // (exc_list's "type slot amount"), so the item count is tokens / fields. + var subPacketCreator = typeof(IPacket).IsAssignableFrom(subType) && remainingTokens > 0 + && !matches[currentIndex].Contains(packetIndexAttribute.SpecialSeparator ?? ".") + ? _packetDeserializerDictionary.Values.FirstOrDefault(s => s.PacketType == subType) + : null; + var tokensPerItem = subPacketCreator == null ? 1 : subPacketCreator.PropertyAmount + 1; + length = (sbyte)((remainingTokens + tokensPerItem - 1) / tokensPerItem); } if (!string.IsNullOrWhiteSpace(separator)) diff --git a/src/NosCore.Packets/NosCore.Packets.csproj b/src/NosCore.Packets/NosCore.Packets.csproj index e85a71e2..07a612d4 100644 --- a/src/NosCore.Packets/NosCore.Packets.csproj +++ b/src/NosCore.Packets/NosCore.Packets.csproj @@ -12,7 +12,7 @@ https://github.com/NosCoreIO/NosCore.Packets.git nostale, noscore, chickenapi, nostale private server source, nostale emulator - 21.1.2 + 21.1.3 false NosCore's Packets (Nostale packets) defined over classes MIT diff --git a/test/NosCore.Packets.Tests/DeserializerTest.cs b/test/NosCore.Packets.Tests/DeserializerTest.cs index 1ef9a685..d3e41c57 100644 --- a/test/NosCore.Packets.Tests/DeserializerTest.cs +++ b/test/NosCore.Packets.Tests/DeserializerTest.cs @@ -5,6 +5,9 @@ // ----------------------------------- using NosCore.Packets.ClientPackets.Chat; +using NosCore.Packets.ClientPackets.Exchanges; +using NosCore.Packets.Attributes; +using System.Reflection; using NosCore.Packets.ClientPackets.Inventory; using NosCore.Packets.ClientPackets.Login; using NosCore.Packets.ClientPackets.Movement; @@ -63,6 +66,8 @@ public class DeserializerTest typeof(CBListPacket), typeof(CScalcPacket), typeof(CreateFamilyPacket), + typeof(ExcListPacket), + typeof(ExcListSubPacket), typeof(UnresolvedPacket) }); @@ -495,5 +500,36 @@ public void PacketWithEmptySpecialSeparatorSplitsEachCharIntoField() Assert.AreEqual((byte)3, packet.ArmorUpgradeRareSubPacket!.Upgrade); Assert.AreEqual((sbyte)5, packet.ArmorUpgradeRareSubPacket.Rare); } + + [TestMethod] + public void DeserializeSpaceSeparatedSubPacketListYieldsOneItemPerSubPacket() + { + var packet = (ExcListPacket)Deserializer.Deserialize("exc_list 21 44 10 53 21 2 87 55"); + Assert.AreEqual(21, packet.Gold); + Assert.AreEqual(44, packet.BankGold); + Assert.HasCount(2, packet.SubPackets!); + Assert.AreEqual(PocketType.Raid, packet.SubPackets![0]!.PocketType); + Assert.AreEqual(53, packet.SubPackets[0]!.Slot); + Assert.AreEqual(21, packet.SubPackets[0]!.Amount); + Assert.AreEqual(PocketType.Etc, packet.SubPackets[1]!.PocketType); + Assert.AreEqual(87, packet.SubPackets[1]!.Slot); + Assert.AreEqual(55, packet.SubPackets[1]!.Amount); + } + + [TestMethod] + public void DeserializeSpaceSeparatedSubPacketListWithASingleSubPacket() + { + var packet = (ExcListPacket)Deserializer.Deserialize("exc_list 5000 0 0 3 2"); + Assert.HasCount(1, packet.SubPackets!); + Assert.AreEqual(3, packet.SubPackets![0]!.Slot); + Assert.AreEqual(2, packet.SubPackets[0]!.Amount); + } + + [TestMethod] + public void ExchangeRequestIsAcceptedWhileTrading() + { + var scopes = typeof(ExchangeRequestPacket).GetCustomAttribute()!.Scopes; + Assert.IsTrue(scopes.HasFlag(Scope.InTrade)); + } } }