Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 16 additions & 2 deletions src/NosCore.Packets/Deserializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,13 @@ public IPacket Deserialize(string packetContent)
var separator = packetIndexAttribute.SpecialSeparator;
if (packetIndexAttribute is PacketListIndexAttribute ind)
{
separator = ind.ListSeparator ?? (typeof(IPacket).IsAssignableFrom(subType) ? separator : ".");
// For IPacket (sub-packet) lists, SpecialSeparator on the list names
// the *inner field* separator inside each sub-packet — not the list
// item separator. The list items are tokenised by the outer packet's
// whitespace. Only ListSeparator (when explicitly set) defines how
// items are joined. For primitive lists, SpecialSeparator remains the
// inter-item separator, defaulting to ".".
separator = ind.ListSeparator ?? (typeof(IPacket).IsAssignableFrom(subType) ? null : separator ?? ".");
}
if (isMaxIndex && string.IsNullOrWhiteSpace(separator))
{
Expand Down Expand Up @@ -359,9 +365,17 @@ public IPacket Deserialize(string packetContent)
var packSeperators = subType.GetProperties()
.Select(prop => prop.GetCustomAttribute<PacketIndexAttribute>()).Where(s => s != null).ToList();

// Fall back to the outer list's SpecialSeparator when the next property
// doesn't override it. Sub-packets like ClinitSubPacket don't decorate
// their own properties, so without this fallback the IndexOf looks for
// "." in strings like "5130502|99|68|547|Trippybell" (not present) and
// every loop iteration appends the whole subpacket — producing
// "X|..X|..X|..X|..X|.." that then fails to parse.
var fieldSeparator = packetIndexAttribute.SpecialSeparator ?? ".";
for (var index = 0; index < packSeperators.Count; index++)
{
var c = index == packSeperators.Count - 1 ? -1 : subpacket.IndexOf(packSeperators[index + 1]!.SpecialSeparator ?? ".", StringComparison.Ordinal);
var isLast = index == packSeperators.Count - 1;
var c = isLast ? -1 : subpacket.IndexOf(packSeperators[index + 1]!.SpecialSeparator ?? fieldSeparator, StringComparison.Ordinal);
if (c == -1)
{
toConvert += subpacket;
Expand Down
2 changes: 1 addition & 1 deletion src/NosCore.Packets/NosCore.Packets.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
<RepositoryUrl>https://github.com/NosCoreIO/NosCore.Packets.git</RepositoryUrl>
<PackageIconUrl></PackageIconUrl>
<PackageTags>nostale, noscore, chickenapi, nostale private server source, nostale emulator</PackageTags>
<Version>17.0.0</Version>
<Version>17.1.0</Version>
<PackageRequireLicenseAcceptance>false</PackageRequireLicenseAcceptance>
<Description>NosCore's Packets (Nostale packets) defined over classes</Description>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
Expand Down
29 changes: 29 additions & 0 deletions test/NosCore.Packets.Tests/DeserializerTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,35 @@ public void DeserializeWithGuid()
Assert.AreEqual("458E0876581FA9A6EFE00A28AA8E75F2", packet.Md5String);
}

[TestMethod]
public void PacketWithListOfSubPacketsWithoutPerPropertySeparatorsSplitsCorrectly()
{
// ClinitPacket is `[PacketListIndex(0, SpecialSeparator = "|")]` over
// ClinitSubPacket whose five properties don't decorate their own
// SpecialSeparator. Prior to 17.1.0 the list-of-sub-packets path
// fell back to "." when looking for each field boundary, which
// wasn't present, so the full sub-packet was appended once per
// property — yielding "X|..X|..X|..X|..X|.." that then failed to parse.
var deserializer = new Deserializer(new[]
{
typeof(ClinitPacket),
typeof(ClinitSubPacket),
});

var packet = (ClinitPacket)deserializer.Deserialize(
"clinit 5130502|99|68|547|Trippybell 7170218|99|94|325|Hamu");

Assert.IsNotNull(packet.SubPackets);
Assert.HasCount(2, packet.SubPackets!);
Assert.AreEqual(5130502L, packet.SubPackets[0]!.CharacterId);
Assert.AreEqual((byte)99, packet.SubPackets[0]!.Level);
Assert.AreEqual((byte)68, packet.SubPackets[0]!.HeroLevel);
Assert.AreEqual(547, packet.SubPackets[0]!.Compliment);
Assert.AreEqual("Trippybell", packet.SubPackets[0]!.CharacterName);
Assert.AreEqual(7170218L, packet.SubPackets[1]!.CharacterId);
Assert.AreEqual("Hamu", packet.SubPackets[1]!.CharacterName);
}

[TestMethod]
public void PacketWithEmptySpecialSeparatorSplitsEachCharIntoField()
{
Expand Down
Loading