View Issue Details

IDProjectCategoryView StatusLast Update
0025684Return of ReckoningGeneralpublic2026-08-08 17:34
Reporterreddozen Assigned To 
PrioritynormalSeveritycrashReproducibilityalways
Status newResolutionopen 
Summary0025684: tome update packet corruption
DescriptionFrom the %LOCALAPPDATA%\CrashDumps .dmp file

crashed midfight during a fort. no lag or packetloss just bonked.

Client crashed at packet decode:
00 0a length
f8 opcode
be bb 29 0f 7a 66 92 84 ae 47 payload

Here's some psuedo code to illustrate the problem and fix

// Busted af
public void SendTok(ushort Entry, bool Print)
{
    PacketOut Out = new PacketOut((byte)Opcodes.F_TOK_ENTRY_UPDATE);
    Out.WriteUInt32(1);
    Out.WriteUInt16((UInt16)Entry); // <-- This is wrong endianness
    Out.WriteByte(1);
    Out.WriteByte((byte)(Print ? 1 : 0));
    Out.WriteByte(1);
    GetPlayer().SendPacket(Out);
}

// Corrected
public void SendTok(ushort Entry, bool Announce, byte Popup = 0, bool Unlocked = true)
{
    // Stop crashing me pls
    if (Entry >= 12000)
    {
        Log.Error("Big Sadness", "Refusing tome entry " + Entry + " as its above the max value of 12000");
        return;
    }

    PacketOut Out = new PacketOut((byte)Opcodes.F_TOK_ENTRY_UPDATE);
    Out.WriteUInt16R(0); // 0 = single entry, 1 = bitmap mode
    Out.WriteUInt16R(1); // count. always 1 cuz not bitmap
    Out.WriteUInt16R(Entry); // <-- FIX LITTLE ENDIAN
    Out.WriteByte((byte)(Unlocked ? 1 : 0)); // 0 = relock the entry, 1 = unlock it
    Out.WriteByte((byte)(Announce ? 1 : 0)); // 0 = silent, 1 = recent list + combat log + some UI shit
    Out.WriteByte(Popup); // popup category: 0 = none, 1/2/3 does some UI shit.
    GetPlayer().SendPacket(Out);
}

// Your bug is probably somewhere in here. dunno why this would fire mid-fort outside zone travel
public void SendAllToks()
{
    byte[] Bits = new byte[1500]; // 1500 * 8 = 12000 entries

    foreach (KeyValuePair<ushort, Character_tok> Kp in _Toks) // Hey! Figure out your concurrency safety here! :)
    {
        ushort Entry = Kp.Value.TokEntry;
        if (Entry >= 12000) // Stop crashing me pls
        {
            Log.Error("Big Sadness", "Refusing tome entry " + Entry + " as its above the max value of 12000");
            continue;
        }
        Bits[Entry >> 3] |= (byte)(1 << (Entry & 7));
    }

    PacketOut Out = new PacketOut((byte)Opcodes.F_TOK_ENTRY_UPDATE);
    Out.WriteUInt16R(1); // 0 = single entry, 1 = bitmap mode
    Out.WriteUInt16R((ushort)Bits.Length); // bitmap count
    Out.WriteUInt16R(0); // base: the entry id that bit 0 of byte 0 maps to. Bug is probably somewhere in here
    Out.Write(Bits, 0, Bits.Length);
    GetPlayer().SendPacket(Out);
}

crashed at the 12000 assert
TagsNo tags attached.

Activities

R1CH

R1CH

2026-08-08 17:30

developer   ~0048667

This is probably unrelated to the TOK system and more a case of the client trying to parse garbage data as a packet. The current backpressure implementation in the server netcode unfortunately can truncate packets if the client isn't receiving fast enough (fort and other low FPS situations usually trigger this since the client receive code doesn't appear to be async) and this result in a desync of the bytestream. The client then starts interpreting the next bytes as best it can, which is why you sometimes see random survey popups, huge amounts of gold or XP / renown being received, etc.

It's entirely possible one of those interpretations looks like a TOK update and triggers this failure. If the TOK packet endianness was wrong then any time a TOK is unlocked would be broken or show garbage, and this isn't the case.
reddozen

reddozen

2026-08-08 17:34

reporter   ~0048668

That wasn't the case in this scenario as the ringbuffer from the crash dump wasn't showing garbled in the next frames, or would be insanely unlikely.

On another note its entirely possible to increase the clientside netcode ringbuffer size so the buffer overruns can't occur like you're describing. You can do this easily in the LAA client.

Issue History

Date Modified Username Field Change
2026-08-08 14:40 reddozen New Issue
2026-08-08 17:30 R1CH Note Added: 0048667
2026-08-08 17:34 reddozen Note Added: 0048668