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");
+ }
}
}