Use this file to discover all available pages before exploring further.
This document specifies every wire packet layout used by Shaiya Core V9’s native chat system. Layouts are inferred from decompiled handlers in game-chat-native/ and psgame-chat-native/; do not edit manually — regenerate .c files via tools/ghidra/. All offsets are after the u16 LE opcode unless noted. (?) marks partial inference. LE = little-endian.
Every packet is framed in a two-byte length prefix followed by ciphertext. The plaintext payload begins with the u16 opcode that the PacketDispatcher routes.
First plaintext field; routed by PacketDispatcher @ 0x5F1E10
Readers (client):PacketRead_Scalar @ 0x005F4700 = memcpy N bytes; PacketRead_String @ 0x005F4780 = up to N bytes (no null terminator on wire).Limits: reader max 0x2000; server send must be < 0x801.
Most chat channels share a compact three-field structure. NetworkSend takes msg_len + 3 as the total plaintext size. Maximum wire text is 255 bytes (single u8).
0xF107 and 0xF109 have no send site in stock Game.exe (objdump finds zero mov $0xF107 / $0xF109 instructions). C→S packets are handled server-side only in AdminChat_ProcessIncoming @ 0x0047FD10. 0xF108 is likewise absent from the client — the server routes bound whisper relay through 0xF102 downstream.
Each opcode maps to one of seven structural patterns. The pattern letter identifies the field layout immediately following the u16 opcode in plaintext.
Handler: Handler_Packet_0502 @ 0x005E0CF0 → vtable +0xF0 → ChatEntitySpawn_vfn @ 0x00593970. This is not a chat box opcode.
/* 0x0502 entity spawn body (15 bytes after opcode) */+0x00 u8 kind // entity type / spawn mode+0x01 u32 field_a+0x05 u32 field_b+0x09 u16 field_c+0x0B u16 field_d+0x0D u16 field_e
Effect: resolves entity via world manager (0x7C4A68); may attach FX (0x459D30), update entity+0x1EC..0x1F4, call EntityStateRefresh @ 0x004153C0. No chat box output.Evidence: game-chat-native/vtable/ChatEntitySpawn_vfn_0xF0_00593970.c
mov $0xF109 @ 0x0047F390 — dual send from Chat_AdminWhisperHelper
Server state:CUser+0x5810 = bound target id (CUser+0x128 of whisper partner). Cleared to 0 on F109 or before rebind.Client UI: recv handlers @ 0x005DE950 / 0x005DE9B0 read char[21] then call vfn +0x344 / +0x348 @ 0x0056BCB0 — a ret 4 stub. ChatWindow_SetWhisperTarget @ 0x0047C690 (vtable +0x198) is not invoked — stock client does not apply the server bind to the whisper UI.
Client inbound opcodes 0x1109, 0x110A, and 0x110B are server push only. If the client sends any of these, Chat_ProcessIncoming hits the default branch → SConnection_Close(9, 0) @ 0x0047FC24 (kick).
1109_A (0x004C6A80): flag=0; if sender in party → CParty_BroadcastPacket; else direct SConnection_Send. Caller @ 0x004A22C6.
1109_B (0x004C6F50): flag=1; iterates zone cells (Zone_FloorWorldToCellIndex @ 0x005250C0, stride 0x124) for users within Math_DistanceRadiusCompare @ 0x0041B8A0. Caller @ 0x004A2640.
Text source (CONFIRMED): builder calls ZoneChat_MessageResolver @ 0x004C6970; copies NUL-terminated bytes from return+4. Map populated at startup from data/cn_string.DB (FUN_00408C70 @ 0x00408C70).0x110A message_id encoding (CONFIRMED):Chat_ScriptWrapper_110A @ 0x004CB3D0 loads a script integer, applies or eax, 0xC00 @ 0x004CB402 before calling Chat_PacketBuilder_110A @ 0x004CB41F. No text is sent on the wire — only the id. Client resolves via GetMsg @ 0x00420DB0 against the same cn_string.DB map.