diff --git a/src/NosCore.Packets/NosCore.Packets.csproj b/src/NosCore.Packets/NosCore.Packets.csproj index 2c30ec1..08e8e3f 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.0 + 21.1.1 false NosCore's Packets (Nostale packets) defined over classes MIT diff --git a/src/NosCore.Packets/Serializer.cs b/src/NosCore.Packets/Serializer.cs index 1c443d6..e80fbfb 100644 --- a/src/NosCore.Packets/Serializer.cs +++ b/src/NosCore.Packets/Serializer.cs @@ -368,7 +368,13 @@ private Expression PropertySerializer(Expression injectedPacket, PacketIndexAttr header = " "; } - specificTypeExpression = PacketSerializer(injectedPacket, indexAttr, specificTypeExpression, t, maxIndex, + // A sub-packet's fields are numbered from its own zero, so the parent's + // maxIndex would mark whichever field happens to share that number as last. + var subMaxIndex = t.GetProperties() + .SelectMany(x => x.GetCustomAttributes(true).OfType()) + .Select(x => x.Index).DefaultIfEmpty(0).Max(); + + specificTypeExpression = PacketSerializer(injectedPacket, indexAttr, specificTypeExpression, t, subMaxIndex, propertySplitter, indexAttr.RemoveHeader ? "" : header ?? ""); break; case var t when t == typeof(IPacket): diff --git a/test/NosCore.Packets.Tests/StringFieldSeparatorTests.cs b/test/NosCore.Packets.Tests/StringFieldSeparatorTests.cs index 6cc59bf..80962b8 100644 --- a/test/NosCore.Packets.Tests/StringFieldSeparatorTests.cs +++ b/test/NosCore.Packets.Tests/StringFieldSeparatorTests.cs @@ -129,5 +129,21 @@ public void AFieldThatOptsInIsEscapedEvenThoughItIsLast() Serializer.Serialize(new MlInfoBrPacket { Name = "Bob", MinilandMessage = "hello there" }), "hello^there"); } + + [TestMethod] + public void ASubPacketFieldIsNotTreatedAsLastBecauseTheParentEndsThere() + { + // InNonPlayerSubPacket.Name is index 9, and so is the sub-packet on InPacket, so + // the name used to inherit the parent's last-field exemption and keep its spaces. + var wire = Serializer.Serialize(new InPacket + { + VisualType = VisualType.Npc, + VNum = "333", + VisualId = 2000001, + InNonPlayerSubPacket = new InNonPlayerSubPacket { Name = "Joyeux Mouton" } + }); + + StringAssert.Contains(wire, "Joyeux^Mouton"); + } } }