chore: Adds missing packets and cleans up packets.html (#2321)

This commit is contained in:
Kamron Batman 2026-01-31 10:20:48 -08:00 • committed by GitHub
parent 0b92eec791
commit 3e8f14a0ac
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
54 changed files with 1976 additions and 1931 deletions

View file

@ -1,4 +1,4 @@
{
{
"category": "Account",
"packets": [
{
@ -295,6 +295,13 @@
"description": "Client patch level"
}
],
"clientVersion": {
"classic": {
"min": "6.0.5.0"
},
"enhanced": {},
"notes": "Replaces the legacy 4-byte seed for clients 6.0.5.0+. Pre-6.0.5.0 clients send only a 4-byte seed without version info."
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 419
@ -335,7 +342,7 @@
{
"id": "0xE1",
"name": "Client Type",
"description": "Sent by the client to identify the client type and version.",
"description": "Sent by the client to identify the client type and version. Added during Kingdom Reborn/Stygian Abyss expansion.",
"direction": "incoming",
"isDynamic": true,
"size": "var",
@ -357,13 +364,20 @@
"name": "Unknown",
"type": "ushort",
"size": 2,
"description": "Unknown"
"value": "0x0001",
"description": "Unknown (always 0x0001)"
},
{
"name": "Client Type",
"type": "ushort",
"type": "enum",
"enumType": "sequential",
"size": 2,
"description": "Client type identifier"
"description": "Client type identifier",
"values": [
{ "value": "0x00", "name": "Classic", "description": "Classic 2D Client" },
{ "value": "0x02", "name": "KR", "description": "Kingdom Reborn Client" },
{ "value": "0x03", "name": "EC", "description": "Enhanced Client (Stygian Abyss)" }
]
},
{
"name": "Version",
@ -371,6 +385,20 @@
"description": "Client version string"
}
],
"related": [
{
"id": "0xBF/0x0F",
"relationship": "related",
"note": "Client Info - similar client type information sent at login"
}
],
"clientVersion": {
"classic": {
"min": "6.0.14.3"
},
"enhanced": {},
"notes": "Added during Kingdom Reborn/Stygian Abyss expansion"
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 200
@ -576,12 +604,19 @@
{
"id": "0xF8",
"relationship": "variant",
"note": "Create Character (New) for 7.0.16.0+ with 4th skill"
"note": "Create Character (New) for Classic 7.0.16.0+ with 4th skill"
},
{
"id": "0x8D",
"relationship": "variant",
"note": "Create Character (EC) for Enhanced Client"
}
],
"clientVersion": {
"max": "7.0.15.x",
"notes": "Replaced by 0xF8 in client 7.0.16.0+"
"classic": {
"max": "7.0.15.x"
},
"notes": "Replaced by 0xF8 in Classic Client 7.0.16.0+. EC uses 0x8D instead."
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
@ -800,18 +835,247 @@
{
"id": "0x00",
"relationship": "variant",
"note": "Create Character (Old) for pre-7.0.16.0 with 3 skills"
"note": "Create Character (Old) for Classic pre-7.0.16.0 with 3 skills"
},
{
"id": "0x8D",
"relationship": "variant",
"note": "Create Character (EC) for Enhanced Client"
}
],
"clientVersion": {
"min": "7.0.16.0",
"notes": "Replaces 0x00, adds 4th starting skill"
"classic": {
"min": "7.0.16.0"
},
"notes": "Classic Client only. Replaces 0x00, adds 4th starting skill. EC uses 0x8D instead."
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs",
"line": 58
},
"notes": "Uses the same handler as 0x00 but with 2 additional bytes for the 4th skill."
},
{
"id": "0x8D",
"name": "Create Character",
"description": "Request to create a new character from Enhanced Client (KR/SA 3D clients). Variable length packet with different field layout than Classic client versions.",
"direction": "incoming",
"isDynamic": true,
"size": "var",
"implemented": false,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0x8D",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Pattern1",
"type": "uint",
"size": 4,
"value": "0xEDEDEDED",
"description": "Fixed pattern"
},
{
"name": "Character Index",
"type": "uint",
"size": 4,
"description": "Character slot index"
},
{
"name": "Name",
"type": "ascii",
"size": 30,
"description": "Character name"
},
{
"name": "Unknown",
"type": "byte[30]",
"size": 30,
"description": "Unknown (possibly password field)"
},
{
"name": "Profession",
"type": "byte",
"size": 1,
"description": "Starting profession"
},
{
"name": "Client Flags",
"type": "byte",
"size": 1,
"description": "Client flags (0x41 or 0x3F)"
},
{
"name": "Gender",
"type": "byte",
"size": 1,
"description": "0=male, 1=female"
},
{
"name": "Race",
"type": "byte",
"size": 1,
"description": "0=human, 1=elf, 2=gargoyle"
},
{
"name": "Strength",
"type": "byte",
"size": 1,
"description": "Starting strength"
},
{
"name": "Dexterity",
"type": "byte",
"size": 1,
"description": "Starting dexterity"
},
{
"name": "Intelligence",
"type": "byte",
"size": 1,
"description": "Starting intelligence"
},
{
"name": "Skin Color",
"type": "ushort",
"size": 2,
"description": "Character skin hue"
},
{
"name": "Unknown2",
"type": "byte[8]",
"size": 8,
"description": "Unknown padding"
},
{
"name": "Skill 1 ID",
"type": "byte",
"size": 1,
"description": "First skill ID"
},
{
"name": "Skill 1 Value",
"type": "byte",
"size": 1,
"description": "First skill starting value"
},
{
"name": "Skill 2 ID",
"type": "byte",
"size": 1,
"description": "Second skill ID"
},
{
"name": "Skill 2 Value",
"type": "byte",
"size": 1,
"description": "Second skill starting value"
},
{
"name": "Skill 3 ID",
"type": "byte",
"size": 1,
"description": "Third skill ID"
},
{
"name": "Skill 3 Value",
"type": "byte",
"size": 1,
"description": "Third skill starting value"
},
{
"name": "Skill 4 ID",
"type": "byte",
"size": 1,
"description": "Fourth skill ID"
},
{
"name": "Skill 4 Value",
"type": "byte",
"size": 1,
"description": "Fourth skill starting value"
},
{
"name": "Unknown3",
"type": "byte[26]",
"size": 26,
"description": "Unknown padding and appearance fields"
},
{
"name": "Hair Color",
"type": "ushort",
"size": 2,
"description": "Hair hue"
},
{
"name": "Hair Style",
"type": "ushort",
"size": 2,
"description": "Hair graphic ID"
},
{
"name": "Shirt Color",
"type": "ushort",
"size": 2,
"description": "Shirt hue"
},
{
"name": "Shirt Style",
"type": "ushort",
"size": 2,
"description": "Shirt graphic ID"
},
{
"name": "Face Color",
"type": "ushort",
"size": 2,
"description": "Face hue"
},
{
"name": "Face Style",
"type": "ushort",
"size": 2,
"description": "Face graphic ID"
},
{
"name": "Beard Color",
"type": "ushort",
"size": 2,
"description": "Facial hair hue"
},
{
"name": "Beard Style",
"type": "ushort",
"size": 2,
"description": "Facial hair graphic ID"
}
],
"related": [
{
"id": "0x00",
"relationship": "variant",
"note": "Create Character (Old) for Classic Client pre-7.0.16.0"
},
{
"id": "0xF8",
"relationship": "variant",
"note": "Create Character (New) for Classic Client 7.0.16.0+"
}
],
"clientVersion": {
"enhanced": {},
"notes": "Enhanced Client only. Uses different field layout with separate gender/race bytes."
},
"notes": "EC clients use this packet instead of 0x00/0xF8. The field layout differs significantly from Classic client versions, with separate gender and race bytes instead of combined genderRace field."
}
]
}

View file

@ -1,4 +1,4 @@
{
{
"category": "Assistant",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Book",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Chat",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Encoded Commands (0xD7)",
"packets": [
{
@ -691,7 +691,10 @@
}
],
"clientVersion": {
"min": "Samurai Empire",
"classic": {
"min": "4.0.3a"
},
"enhanced": {},
"notes": "Added with Samurai Empire expansion"
},
"source": {
@ -761,7 +764,10 @@
}
],
"clientVersion": {
"min": "Samurai Empire",
"classic": {
"min": "4.0.3a"
},
"enhanced": {},
"notes": "Added with Samurai Empire expansion"
},
"source": {

View file

@ -1,4 +1,4 @@
{
{
"category": "Item",
"tags": ["Mobile"],
"packets": [

View file

@ -1,4 +1,4 @@
{
{
"category": "Extended Commands (0xBF)",
"packets": [
{
@ -604,9 +604,10 @@
"id": "0xBF/0x0F",
"subId": "0x0F",
"name": "Client Info",
"description": "Client type information (Spy on Client). No data is read from this packet.",
"description": "Client type information sent once at login. ModernUO currently ignores this packet data.",
"direction": "incoming",
"isDynamic": true,
"implemented": false,
"size": "var",
"fields": [
{
@ -626,14 +627,41 @@
"name": "Sub-Command",
"type": "ushort",
"size": 2,
"value": "0x0F",
"value": "0x000F",
"description": "Client Info subcommand"
},
{
"name": "Unknown",
"type": "byte",
"size": 1,
"value": "0x0A",
"description": "Unknown (always 0x0A)"
},
{
"name": "Client Type",
"type": "enum",
"enumType": "sequential",
"size": 4,
"description": "Client type flag (same as character create/login)",
"values": [
{ "value": "0x00", "name": "Classic", "description": "Classic 2D Client" },
{ "value": "0x02", "name": "KR", "description": "Kingdom Reborn Client" },
{ "value": "0x03", "name": "EC", "description": "Enhanced Client (Stygian Abyss)" }
]
}
],
"related": [
{
"id": "0xE1",
"relationship": "related",
"note": "Client Type packet - similar client type information"
}
],
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs",
"line": 52
}
},
"notes": "ModernUO registers this packet but ignores its data (calls Empty handler). The client type should match the value in 0xE1 Client Type packet."
},
{
"id": "0xBF/0x10",

View file

@ -0,0 +1,134 @@
{
"category": "FreeShard Protocol (0xF1)",
"packets": [
{
"id": "0xF1",
"name": "FreeShard Protocol",
"description": "Bundle packet for freeshard-specific commands (UOGateway). Sub-command is a single byte.",
"direction": "incoming",
"isDynamic": true,
"size": "var",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xF1",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "byte",
"size": 1,
"description": "Subcommand ID"
},
{
"name": "Data",
"type": "byte[]",
"description": "Subcommand-specific data"
}
],
"subpackets": [
{
"subId": "0xFE",
"name": "Query Compact Shard Stats",
"direction": "incoming"
},
{
"subId": "0xFF",
"name": "Query Extended Shard Stats",
"direction": "incoming"
}
],
"source": {
"file": "Projects/UOContent/Network/FreeshardProtocol.cs",
"line": 21
}
},
{
"id": "0xF1/0xFE",
"subId": "0xFE",
"name": "Query Compact Shard Stats",
"description": "Query server for compact statistics. Server responds with 0x51.",
"direction": "incoming",
"isDynamic": true,
"size": "var",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xF1",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "byte",
"size": 1,
"value": "0xFE",
"description": "Query Compact Shard Stats subcommand"
}
],
"notes": "Outgame only. Requires uogateway.enabled configuration.",
"related": [
{
"id": "0x51",
"relationship": "response",
"note": "Compact Shard Stats response"
}
],
"source": {
"file": "Projects/UOContent/Network/UOGateway.cs",
"line": 31
}
},
{
"id": "0xF1/0xFF",
"subId": "0xFF",
"name": "Query Extended Shard Stats",
"description": "Query server for extended statistics. Server responds with raw UTF-8 string.",
"direction": "incoming",
"isDynamic": true,
"size": "var",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xF1",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "byte",
"size": 1,
"value": "0xFF",
"description": "Query Extended Shard Stats subcommand"
}
],
"notes": "Outgame only. Requires uogateway.enabled configuration. Response is a raw UTF-8 string (no packet wrapper): 'ModernUO, Name={name}, Age={hours}, Clients={count}, Items={count}, Chars={count}, Mem={kb}K, Ver=2\\0'",
"source": {
"file": "Projects/UOContent/Network/UOGateway.cs",
"line": 32
}
}
]
}

View file

@ -0,0 +1,116 @@
{
"category": "Gump",
"packets": [
{
"id": "0xB1",
"name": "Gump Response",
"description": "Client response to a generic gump dialog (button press, checkbox/radio selections, text entries).",
"direction": "incoming",
"isDynamic": true,
"size": "var",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xB1",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Serial from the 0xB0/0xDD gump packet"
},
{
"name": "Gump ID",
"type": "uint",
"size": 4,
"description": "Gump type ID from the 0xB0/0xDD gump packet"
},
{
"name": "Button ID",
"type": "uint",
"size": 4,
"description": "ID of button pressed (0 if gump closed without pressing a button)"
},
{
"name": "Switch Count",
"type": "uint",
"size": 4,
"description": "Number of active switches (checkboxes/radio buttons)"
},
{
"name": "Switches",
"type": "array",
"description": "Array of switch IDs that are active/checked",
"entries": [
{
"name": "Switch ID",
"type": "uint",
"size": 4,
"description": "ID of an active switch"
}
]
},
{
"name": "Text Entry Count",
"type": "uint",
"size": 4,
"description": "Number of text entries"
},
{
"name": "Text Entries",
"type": "array",
"description": "Array of text entry responses",
"entries": [
{
"name": "Entry ID",
"type": "ushort",
"size": 2,
"description": "Text entry field ID"
},
{
"name": "Text Length",
"type": "ushort",
"size": 2,
"description": "Length of text in characters"
},
{
"name": "Text",
"type": "unicode-be",
"size": "var",
"description": "UTF-16 BE encoded text (length * 2 bytes, not null-terminated)"
}
]
}
],
"related": [
{
"id": "0xB0",
"relationship": "response",
"note": "Generic Gump (uncompressed) - server sends this to display the gump"
},
{
"id": "0xDD",
"relationship": "response",
"note": "Compressed Gump - server sends this to display a compressed gump"
}
],
"clientVersion": {
"classic": {},
"enhanced": {}
},
"source": {
"file": "Projects/UOContent/Gumps/Base/GumpSystem.cs",
"line": 31
}
}
]
}

View file

@ -0,0 +1,188 @@
{
"category": "Hardware",
"packets": [
{
"id": "0xD9",
"name": "Hardware Info",
"description": "Client sends hardware and system information. Also known as 'Spy on Client' packet.",
"direction": "incoming",
"isDynamic": false,
"size": 268,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xD9",
"description": "Packet identifier"
},
{
"name": "Unknown",
"type": "byte",
"size": 1,
"description": "Unknown (1 for pre-4.0.1a, 2 for 4.0.1a+)"
},
{
"name": "Instance ID",
"type": "int",
"size": 4,
"description": "UO client instance identifier"
},
{
"name": "OS Major",
"type": "int",
"size": 4,
"description": "Operating system major version"
},
{
"name": "OS Minor",
"type": "int",
"size": 4,
"description": "Operating system minor version"
},
{
"name": "OS Revision",
"type": "int",
"size": 4,
"description": "Operating system revision"
},
{
"name": "CPU Manufacturer",
"type": "byte",
"size": 1,
"description": "CPU manufacturer code"
},
{
"name": "CPU Family",
"type": "int",
"size": 4,
"description": "CPU family identifier"
},
{
"name": "CPU Model",
"type": "int",
"size": 4,
"description": "CPU model number"
},
{
"name": "CPU Clock Speed",
"type": "int",
"size": 4,
"description": "CPU clock speed in MHz"
},
{
"name": "CPU Quantity",
"type": "byte",
"size": 1,
"description": "Number of CPUs/cores"
},
{
"name": "Physical Memory",
"type": "int",
"size": 4,
"description": "Physical memory in MB"
},
{
"name": "Screen Width",
"type": "int",
"size": 4,
"description": "Screen width in pixels"
},
{
"name": "Screen Height",
"type": "int",
"size": 4,
"description": "Screen height in pixels"
},
{
"name": "Screen Depth",
"type": "int",
"size": 4,
"description": "Screen color depth in bits"
},
{
"name": "DirectX Major",
"type": "short",
"size": 2,
"description": "DirectX major version"
},
{
"name": "DirectX Minor",
"type": "short",
"size": 2,
"description": "DirectX minor version"
},
{
"name": "Video Card Description",
"type": "unicode-le",
"size": 128,
"description": "Video card description string (64 chars, little-endian UTF-16)"
},
{
"name": "Video Card Vendor ID",
"type": "int",
"size": 4,
"description": "Video card vendor identifier"
},
{
"name": "Video Card Device ID",
"type": "int",
"size": 4,
"description": "Video card device identifier"
},
{
"name": "Video Card Memory",
"type": "int",
"size": 4,
"description": "Video card memory in MB"
},
{
"name": "Distribution",
"type": "byte",
"size": 1,
"description": "Distribution type"
},
{
"name": "Clients Running",
"type": "byte",
"size": 1,
"description": "Number of UO clients currently running"
},
{
"name": "Clients Installed",
"type": "byte",
"size": 1,
"description": "Number of UO clients installed"
},
{
"name": "Partial Installed",
"type": "byte",
"size": 1,
"description": "Partial installation flag"
},
{
"name": "Language",
"type": "unicode-le",
"size": 8,
"description": "Language code (4 chars, little-endian UTF-16)"
},
{
"name": "Unknown2",
"type": "ascii",
"size": 64,
"description": "Unknown data"
}
],
"clientVersion": {
"classic": {},
"enhanced": {},
"notes": "Packet size is 268 bytes (0x10C) for clients 4.0.1a+"
},
"source": {
"file": "Projects/UOContent/Misc/HardwareInfo.cs",
"line": 93
},
"notes": "This packet is sent automatically by the client after login. The server uses this to track hardware information for debugging and statistics purposes."
}
]
}

View file

@ -0,0 +1,37 @@
{
"category": "House",
"packets": [
{
"id": "0xFB",
"name": "Public House Content",
"description": "Client toggles whether to receive content updates for public houses. When enabled, the server sends container contents for publicly accessible houses.",
"direction": "incoming",
"isDynamic": false,
"size": 2,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xFB",
"description": "Packet identifier"
},
{
"name": "Show Contents",
"type": "bool",
"size": 1,
"description": "0 = hide public house contents, 1 = show public house contents"
}
],
"clientVersion": {
"classic": {},
"enhanced": {}
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingHousePackets.cs",
"line": 24
},
"notes": "This packet allows clients to opt-in or opt-out of receiving container content data for publicly accessible houses, which can reduce bandwidth for players who don't need to see inside public houses."
}
]
}

View file

@ -1,4 +1,4 @@
{
{
"category": "Items",
"packets": [
{
@ -146,7 +146,11 @@
}
],
"clientVersion": {
"feature": "ContainerGridLines adds gridLocation byte"
"classic": {
"min": "6.0.1.7"
},
"enhanced": {},
"notes": "ContainerGridLines adds gridLocation byte"
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
@ -235,6 +239,9 @@
}
}
],
"clientVersion": {
"enhanced": {}
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 112
@ -283,6 +290,9 @@
}
}
],
"clientVersion": {
"enhanced": {}
},
"source": {
"file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs",
"line": 125

View file

@ -1,4 +1,4 @@
{
{
"category": "Map",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Message",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Mobile",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Movement",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Player",
"packets": [
{

View file

@ -0,0 +1,32 @@
{
"category": "Store",
"packets": [
{
"id": "0xFA",
"name": "Open UO Store",
"description": "Client requests to open the Ultima Store interface. Sent when player clicks the UO Store button in the client toolbar (Classic) or selects Ultima Store from the menu (Enhanced).",
"direction": "incoming",
"isDynamic": false,
"size": 1,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xFA",
"description": "Packet identifier"
}
],
"clientVersion": {
"classic": {},
"enhanced": {},
"notes": "Ultima Store feature"
},
"source": {
"file": "Projects/UOContent/Engines/UltimaStore/UltimaStorePackets.cs",
"line": 10
},
"notes": "The Ultima Store is an in-game microtransaction store on official servers. ModernUO includes a placeholder that displays a 'not available' message. Free shards may implement their own store functionality using this packet trigger."
}
]
}

View file

@ -1,4 +1,4 @@
{
{
"category": "Targeting",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Vendor",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Account",
"packets": [
{
@ -983,7 +983,9 @@
}
],
"clientVersion": {
"feature": "ExtendedSupportedFeatures determines which variant is sent"
"classic": {},
"enhanced": {},
"notes": "ExtendedSupportedFeatures determines which variant is sent"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Quest",
"packets": [
{
@ -127,7 +127,11 @@
}
],
"clientVersion": {
"feature": "HighSeas (7.0.9.0+) adds target serial"
"classic": {
"min": "7.0.9.0"
},
"enhanced": {},
"notes": "HighSeas (7.0.9.0+) adds target serial. Pre-HS clients use 6-byte variant (max 7.0.8.x), HS+ clients use 10-byte variant."
},
"source": {
"file": "Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Assistant",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Boat",
"packets": [
{
@ -106,7 +106,11 @@
}
],
"clientVersion": {
"feature": "HighSeas"
"classic": {
"min": "7.0.9.0"
},
"enhanced": {},
"notes": "High Seas expansion feature"
},
"source": {
"file": "Projects/UOContent/Multis/Boats/BoatPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Book",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Buff Icon",
"packets": [
{
@ -292,8 +292,11 @@
}
],
"clientVersion": {
"min": "5.0.2b",
"feature": "BuffIcon"
"classic": {
"min": "5.0.2b"
},
"enhanced": {},
"notes": "BuffIcon feature supported in Classic Client 5.0.2b+"
},
"source": {
"file": "Projects/UOContent/Engines/BuffIcons/BuffIconPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Bulletin Board",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Chat",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Combat",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Container",
"packets": [
{
@ -71,7 +71,11 @@
}
],
"clientVersion": {
"feature": "HighSeas adds containerType field"
"classic": {
"min": "7.0.9.0"
},
"enhanced": {},
"notes": "HighSeas adds containerType field"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
@ -221,7 +225,11 @@
}
],
"clientVersion": {
"feature": "ContainerGridLines adds gridLocation byte"
"classic": {
"min": "6.0.1.7"
},
"enhanced": {},
"notes": "ContainerGridLines adds gridLocation byte"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs",
@ -429,7 +437,11 @@
}
],
"clientVersion": {
"feature": "ContainerGridLines (6.0.1.7+) adds gridLocation byte per item"
"classic": {
"min": "6.0.1.7"
},
"enhanced": {},
"notes": "ContainerGridLines (6.0.1.7+) adds gridLocation byte per item"
},
"notes": "Also used for corpse contents. Corpses are special containers that display equipped items on a body graphic. Use with 0x89 Corpse Equipment for full corpse display.",
"source": {
@ -508,8 +520,11 @@
}
],
"clientVersion": {
"min": "5.0.0a",
"feature": "NewSpellbook (Core.AOS \u0026\u0026 ns.NewSpellbook)"
"classic": {
"min": "5.0.0a"
},
"enhanced": {},
"notes": "NewSpellbook feature (Core.AOS)"
},
"notes": "Used when Core.AOS \u0026\u0026 ns.NewSpellbook. Otherwise, old 0x3C format is used with spells as pseudo-items.",
"source": {
@ -575,7 +590,11 @@
}
],
"clientVersion": {
"feature": "HighSeas"
"classic": {
"min": "7.0.9.0"
},
"enhanced": {},
"notes": "HighSeas expansion feature"
},
"notes": "Uses PacketContainerBuilder for efficient dynamic growth. Commonly used by boat system to batch all visible entities on deck. Minimum packet length is 5 bytes (header only).",
"source": {

View file

@ -1,4 +1,4 @@
{
{
"category": "Context Menu",
"packets": [
{
@ -201,7 +201,11 @@
}
],
"clientVersion": {
"feature": "NewHaven clients (6.0.0.0+) use command 0x02"
"classic": {
"min": "6.0.0.0"
},
"enhanced": {},
"notes": "NewHaven clients (6.0.0.0+) use command 0x02"
},
"source": {
"file": "Projects/UOContent/Context Menus/ContextMenuSystem.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Combat",
"packets": [
{
@ -30,10 +30,13 @@
}
],
"clientVersion": {
"min": "5.0.0a",
"feature": "DamagePacket"
"classic": {
"min": "5.0.0a"
},
"enhanced": {},
"notes": "Used by Enhanced Client (all versions) and Classic Client 5.0.0a+"
},
"notes": "For pre-5.0.0a clients, use 0xBF/0x22 instead.",
"notes": "For pre-5.0.0a clients, use 0xBF/0x22 instead. Enhanced Client always uses this packet format (ushort damage allows values up to 65535).",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs",
"line": 34
@ -89,10 +92,12 @@
}
],
"clientVersion": {
"max": "5.0.0a",
"notes": "For clients before DamagePacket feature"
"classic": {
"max": "5.0.0a"
},
"notes": "For Classic Client before DamagePacket feature. Not used by Enhanced Client."
},
"notes": "Damage is capped at 255 for old clients.",
"notes": "Damage is capped at 255 for old clients. Classic Client only; Enhanced Client uses 0x0B packet.",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs",
"line": 40

View file

@ -1,4 +1,4 @@
{
{
"category": "Effects",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Item",
"tags": ["Mobile"],
"packets": [
@ -86,8 +86,11 @@
}
],
"clientVersion": {
"min": "4.0.0a",
"feature": "AOS tooltips"
"classic": {
"min": "4.0.0a"
},
"enhanced": {},
"notes": "AOS tooltips feature"
},
"notes": "Hash is calculated by XORing each property\u0027s cliloc number with ((hash \u003e\u003e 31) \u0026 1) ^ (hash \u003c\u003c 1). Properties are cliloc entries with optional Unicode LE arguments separated by tabs.",
"source": {
@ -385,8 +388,11 @@
}
],
"clientVersion": {
"min": "7.0.0.0",
"feature": "StygianAbyss"
"classic": {
"min": "7.0.0.0"
},
"enhanced": {},
"notes": "StygianAbyss expansion feature"
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Equipment",
"packets": [
{

View file

@ -0,0 +1,70 @@
{
"category": "FreeShard Protocol",
"packets": [
{
"id": "0x51",
"name": "Compact Shard Stats",
"description": "Server response to compact shard stats query (0xF1/0xFE).",
"direction": "outgoing",
"isDynamic": false,
"size": 27,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0x51",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "0x001B",
"description": "Packet length (27)"
},
{
"name": "Clients",
"type": "int",
"size": 4,
"description": "Current client count"
},
{
"name": "Items",
"type": "int",
"size": 4,
"description": "Total item count"
},
{
"name": "Mobiles",
"type": "int",
"size": 4,
"description": "Total mobile count"
},
{
"name": "Age",
"type": "uint",
"size": 4,
"description": "Server uptime in seconds"
},
{
"name": "Memory",
"type": "long",
"size": 8,
"description": "Memory usage in bytes"
}
],
"related": [
{
"id": "0xF1/0xFE",
"relationship": "request",
"note": "Query Compact Shard Stats request"
}
],
"source": {
"file": "Projects/UOContent/Network/UOGateway.cs",
"line": 60
}
}
]
}

View file

@ -1,4 +1,4 @@
{
{
"category": "Gump",
"packets": [
{
@ -216,7 +216,9 @@
},
{
"name": "Noresize",
"description": "Prevent resizing (Enhanced Client)"
"description": "Prevent resizing (Enhanced Client)",
"tags": ["EC"],
"notes": "Enhanced Client only"
},
{
"name": "Nodispose",
@ -388,7 +390,9 @@
},
{
"name": "Picinpic",
"description": "Cropped sprite from gump",
"description": "Cropped sprite from gump (sprite image rendering)",
"tags": ["EC"],
"notes": "Also known as GumpSpriteImage. EC-compatible.",
"args": [
{
"name": "X",
@ -965,7 +969,9 @@
},
{
"name": "Tooltip",
"description": "Tooltip on previous element",
"description": "Tooltip on previous element (GumpTooltip)",
"tags": ["EC"],
"notes": "EC-compatible tooltip display.",
"args": [
{
"name": "Cliloc",
@ -982,7 +988,9 @@
},
{
"name": "Itemproperty",
"description": "Display item\u0027s OPL tooltip",
"description": "Display item's OPL tooltip (GumpItemProperty)",
"tags": ["EC"],
"notes": "EC-compatible property display for items.",
"args": [
{
"name": "Serial",
@ -1001,6 +1009,12 @@
"description": "Master gump identifier"
}
]
},
{
"name": "Echandleinput",
"description": "EC-specific input handler",
"tags": ["EC"],
"notes": "Enhanced Client only"
}
]
},
@ -1030,8 +1044,11 @@
}
],
"clientVersion": {
"min": "3.0.0",
"feature": "Compressed gumps"
"classic": {
"min": "3.0.0"
},
"enhanced": {},
"notes": "Compressed gumps supported since Classic Client 3.0.0"
},
"notes": "Layout uses ASCII encoding only. The compressed lengths include a +4 offset. Decompression produces: layout as ASCII text, strings as length-prefixed UTF-16 BE entries.",
"source": {

View file

@ -1,4 +1,4 @@
{
{
"category": "House",
"packets": [
{
@ -153,8 +153,11 @@
}
],
"clientVersion": {
"min": "4.0.0a",
"feature": "AOS House Customization"
"classic": {
"min": "4.0.0a"
},
"enhanced": {},
"notes": "AOS House Customization feature"
},
"source": {
"file": "Projects/UOContent/Multis/Houses/HousePackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Items",
"packets": [
{
@ -90,7 +90,9 @@
],
"notes": "For Stygian Abyss+ clients, use 0xF3 World Entity instead.",
"clientVersion": {
"max": "6.0.14.2",
"classic": {
"max": "6.0.14.2"
},
"notes": "Replaced by 0xF3 for SA+ clients"
},
"source": {

View file

@ -1,4 +1,4 @@
{
{
"category": "Light",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Mahjong",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Map",
"packets": [
{
@ -412,8 +412,11 @@
}
],
"clientVersion": {
"min": "7.0.13.0",
"feature": "NewCharacterList"
"classic": {
"min": "7.0.13.0"
},
"enhanced": {},
"notes": "NewCharacterList feature"
},
"source": {
"file": "Projects/UOContent/Items/Maps/MapItemPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Menu",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Message",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Mobile",
"packets": [
{
@ -1104,8 +1104,8 @@
},
{
"id": "0x78",
"name": "Mobile Incoming",
"description": "Full mobile information including equipped items. Sent when a mobile enters view range.",
"name": "Mobile Incoming (Old)",
"description": "Full mobile information including equipped items. Sent when a mobile enters view range. Pre-Stygian Abyss version.",
"direction": "outgoing",
"isDynamic": true,
"size": "23+",
@ -1232,7 +1232,7 @@
"name": "Item ID",
"type": "ushort",
"size": 2,
"description": "Item graphic ID (bit 0x8000 = hue follows for old clients)"
"description": "Item graphic ID (15-bit, 0x7FFF mask). Bit 0x8000 indicates hue follows."
},
{
"name": "Layer",
@ -1244,8 +1244,8 @@
"name": "Hue",
"type": "short",
"size": 2,
"description": "Item hue (only if bit 0x8000 set or NewMobileIncoming)",
"condition": "hue flag or NewMobileIncoming"
"description": "Item hue (only present if bit 0x8000 set on Item ID)",
"condition": "Item ID & 0x8000"
}
]
}
@ -1259,9 +1259,351 @@
}
],
"clientVersion": {
"feature": "NewMobileIncoming",
"notes": "NewMobileIncoming clients always include hue field for equipment"
"classic": { "max": "6.x.x.x" },
"notes": "Pre-Stygian Abyss. Equipment hue only sent when non-zero (indicated by 0x8000 flag on ItemID)."
},
"related": [
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (SA) for 7.0.0.0+" },
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (New) for 7.0.33.1+" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 601
}
},
{
"id": "0x78",
"name": "Mobile Incoming (SA)",
"description": "Full mobile information including equipped items. Sent when a mobile enters view range. Stygian Abyss version with updated packet flags.",
"direction": "outgoing",
"isDynamic": true,
"size": "23+",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0x78",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Mobile serial"
},
{
"name": "Body",
"type": "short",
"size": 2,
"description": "Body/graphic ID"
},
{
"name": "X",
"type": "short",
"size": 2,
"description": "X coordinate"
},
{
"name": "Y",
"type": "short",
"size": 2,
"description": "Y coordinate"
},
{
"name": "Z",
"type": "sbyte",
"size": 1,
"description": "Z coordinate"
},
{
"name": "Direction",
"type": "byte",
"size": 1,
"description": "Facing direction"
},
{
"name": "Hue",
"type": "short",
"size": 2,
"description": "Hue/color"
},
{
"name": "Flags",
"type": "byte",
"size": 1,
"description": "Packet flags"
},
{
"name": "Notoriety",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Notoriety flag",
"values": [
{
"value": 0,
"name": "Innocent",
"description": "Blue - innocent player"
},
{
"value": 1,
"name": "Friend",
"description": "Green - ally/friend"
},
{
"value": 2,
"name": "Attackable",
"description": "Gray - can be attacked"
},
{
"value": 3,
"name": "Criminal",
"description": "Gray - criminal flag"
},
{
"value": 4,
"name": "Enemy",
"description": "Orange - enemy"
},
{
"value": 5,
"name": "Murderer",
"description": "Red - murderer"
},
{
"value": 6,
"name": "Invulnerable",
"description": "Yellow - invulnerable"
}
]
},
{
"name": "Equipment",
"type": "array",
"description": "Equipped items (terminated by 0x00000000)",
"loop": {
"countField": "variable (until terminator)",
"fields": [
{
"name": "Item Serial",
"type": "uint",
"size": 4,
"description": "Item serial (0 = end of list)"
},
{
"name": "Item ID",
"type": "ushort",
"size": 2,
"description": "Item graphic ID (15-bit, 0x7FFF mask). Bit 0x8000 indicates hue follows."
},
{
"name": "Layer",
"type": "byte",
"size": 1,
"description": "Equipment layer"
},
{
"name": "Hue",
"type": "short",
"size": 2,
"description": "Item hue (only present if bit 0x8000 set on Item ID)",
"condition": "Item ID & 0x8000"
}
]
}
},
{
"name": "Terminator",
"type": "int",
"size": 4,
"value": "0x00000000",
"description": "Equipment list terminator"
}
],
"clientVersion": {
"classic": { "min": "7.0.0.0", "max": "7.0.33.0" },
"enhanced": {},
"notes": "Stygian Abyss clients. Equipment hue only sent when non-zero (indicated by 0x8000 flag on ItemID)."
},
"related": [
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (Old) for pre-7.0.0.0" },
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (New) for 7.0.33.1+" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 601
}
},
{
"id": "0x78",
"name": "Mobile Incoming (New)",
"description": "Full mobile information including equipped items. Sent when a mobile enters view range. NewMobileIncoming version with full 16-bit ItemID and always-present hue field.",
"direction": "outgoing",
"isDynamic": true,
"size": "23+",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0x78",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Mobile serial"
},
{
"name": "Body",
"type": "short",
"size": 2,
"description": "Body/graphic ID"
},
{
"name": "X",
"type": "short",
"size": 2,
"description": "X coordinate"
},
{
"name": "Y",
"type": "short",
"size": 2,
"description": "Y coordinate"
},
{
"name": "Z",
"type": "sbyte",
"size": 1,
"description": "Z coordinate"
},
{
"name": "Direction",
"type": "byte",
"size": 1,
"description": "Facing direction"
},
{
"name": "Hue",
"type": "short",
"size": 2,
"description": "Hue/color"
},
{
"name": "Flags",
"type": "byte",
"size": 1,
"description": "Packet flags"
},
{
"name": "Notoriety",
"type": "enum",
"enumType": "sequential",
"size": 1,
"description": "Notoriety flag",
"values": [
{
"value": 0,
"name": "Innocent",
"description": "Blue - innocent player"
},
{
"value": 1,
"name": "Friend",
"description": "Green - ally/friend"
},
{
"value": 2,
"name": "Attackable",
"description": "Gray - can be attacked"
},
{
"value": 3,
"name": "Criminal",
"description": "Gray - criminal flag"
},
{
"value": 4,
"name": "Enemy",
"description": "Orange - enemy"
},
{
"value": 5,
"name": "Murderer",
"description": "Red - murderer"
},
{
"value": 6,
"name": "Invulnerable",
"description": "Yellow - invulnerable"
}
]
},
{
"name": "Equipment",
"type": "array",
"description": "Equipped items (terminated by 0x00000000)",
"loop": {
"countField": "variable (until terminator)",
"fields": [
{
"name": "Item Serial",
"type": "uint",
"size": 4,
"description": "Item serial (0 = end of list)"
},
{
"name": "Item ID",
"type": "ushort",
"size": 2,
"description": "Item graphic ID (full 16-bit, 0xFFFF mask)"
},
{
"name": "Layer",
"type": "byte",
"size": 1,
"description": "Equipment layer"
},
{
"name": "Hue",
"type": "short",
"size": 2,
"description": "Item hue (always present)"
}
]
}
},
{
"name": "Terminator",
"type": "int",
"size": 4,
"value": "0x00000000",
"description": "Equipment list terminator"
}
],
"clientVersion": {
"classic": { "min": "7.0.33.1" },
"notes": "NewMobileIncoming clients. Equipment always includes hue field (no 0x8000 flag needed). ItemID uses full 16-bit range."
},
"related": [
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (Old) for pre-7.0.0.0" },
{ "id": "0x78", "relationship": "variant", "note": "Mobile Incoming (SA) for 7.0.0.0-7.0.33.0" }
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 601
@ -1625,18 +1967,21 @@
},
{
"name": "Show Bar",
"type": "short",
"type": "enum",
"size": 2,
"value": "0x0001",
"description": "Show bar (always 1)"
"description": "Show bar flag. If 0, packet ends here (no subsequent fields sent).",
"values": [
{ "value": "0", "name": "Hide", "description": "Hide healthbar, packet ends here" },
{ "value": "1", "name": "Show", "description": "Show healthbar, following fields included" }
]
},
{
"name": "Healthbar Type",
"type": "enum",
"size": 2,
"description": "Type of healthbar overlay",
"description": "Type of healthbar overlay (only sent if Show Bar = 1)",
"values": [
{ "value": "1", "name": "Poison", "description": "Poison status bar" },
{ "value": "1", "name": "Poison", "description": "Poison status bar (green)" },
{ "value": "2", "name": "Yellow", "description": "Yellow/invulnerable bar" }
]
},
@ -1644,7 +1989,7 @@
"name": "Level",
"type": "enum",
"size": 1,
"description": "Status level",
"description": "Status level (only sent if Show Bar = 1)",
"values": [
{ "value": "0", "name": "Off", "description": "Status disabled" },
{ "value": "1", "name": "Level1/On", "description": "Poison level 1 or yellow on" },
@ -1654,10 +1999,97 @@
]
}
],
"related": [
{
"id": "0x16",
"relationship": "variant",
"note": "Mobile Healthbar (EC) - Enhanced Client version"
}
],
"clientVersion": {
"classic": {},
"notes": "Classic Client only. EC uses 0x16 instead."
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 419
}
},
"notes": "When Show Bar is 0, the packet is only 9 bytes (no Healthbar Type or Level fields). Poison (green) overrides yellow coloring."
},
{
"id": "0x16",
"name": "Mobile Healthbar",
"description": "Updates a mobile's healthbar status for Enhanced Client (poison level, yellow bar for invulnerability).",
"direction": "outgoing",
"isDynamic": true,
"implemented": false,
"size": "9 or 12",
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0x16",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"description": "Packet length (9 or 12)"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Mobile serial"
},
{
"name": "Show Bar",
"type": "enum",
"size": 2,
"description": "Show bar flag. If 0, packet ends here (no subsequent fields sent).",
"values": [
{ "value": "0", "name": "Hide", "description": "Hide healthbar, packet ends here" },
{ "value": "1", "name": "Show", "description": "Show healthbar, following fields included" }
]
},
{
"name": "Healthbar Type",
"type": "enum",
"size": 2,
"description": "Type of healthbar overlay (only sent if Show Bar = 1)",
"values": [
{ "value": "1", "name": "Poison", "description": "Poison status bar (green)" },
{ "value": "2", "name": "Yellow", "description": "Yellow/invulnerable bar" }
]
},
{
"name": "Level",
"type": "enum",
"size": 1,
"description": "Status level (only sent if Show Bar = 1)",
"values": [
{ "value": "0", "name": "Off", "description": "Status disabled" },
{ "value": "1", "name": "Level1/On", "description": "Poison level 1 or yellow on" },
{ "value": "2", "name": "Level2", "description": "Poison level 2 (Greater)" },
{ "value": "3", "name": "Level3", "description": "Poison level 3 (Deadly)" },
{ "value": "4", "name": "Level4", "description": "Poison level 4 (Lethal)" }
]
}
],
"related": [
{
"id": "0x17",
"relationship": "variant",
"note": "Mobile Healthbar (Classic) - Classic Client version"
}
],
"clientVersion": {
"enhanced": {},
"notes": "Enhanced Client only. Classic uses 0x17 instead."
},
"notes": "When Show Bar is 0, the packet is only 9 bytes (no Healthbar Type or Level fields). Poison (green) overrides yellow coloring. ModernUO currently sends 0x17 to all clients; this EC variant needs implementation."
},
{
"id": "0xAF",
@ -1697,61 +2129,6 @@
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 78
}
},
{
"id": "0xBF",
"subId": "0x19",
"name": "Bonded Status",
"description": "Indicates whether a mobile (pet) is bonded to its owner.",
"direction": "outgoing",
"isDynamic": false,
"size": 11,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xBF",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "0x000B",
"description": "Packet length (11)"
},
{
"name": "Sub-Command",
"type": "ushort",
"size": 2,
"value": "0x0019",
"description": "Sub-command for bonded status"
},
{
"name": "Command",
"type": "byte",
"size": 1,
"value": "0x00",
"description": "Command type (0 for bonded)"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Mobile serial"
},
{
"name": "Bonded",
"type": "bool",
"size": 1,
"description": "Bonded status"
}
],
"source": {
"file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs",
"line": 44
}
}
]
}

View file

@ -1,4 +1,4 @@
{
{
"category": "Movement",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Party",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Player",
"packets": [
{
@ -904,95 +904,249 @@
},
{
"id": "0xBF/0x19",
"name": "Stat Lock Info",
"description": "Sends stat lock states (STR/DEX/INT) to client.",
"name": "Extended Status",
"description": "Multi-purpose status packet. The Type byte determines the payload: Type 0 for pet bonded status, Type 2/5 for player stat locks.",
"direction": "outgoing",
"isDynamic": false,
"size": 12,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xBF",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "12",
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "short",
"size": 2,
"value": "0x19",
"description": "Subcommand (Stat Lock Info)"
},
{
"name": "Type",
"type": "byte",
"size": 1,
"value": "0x02",
"description": "Type (2 = stat locks)"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Mobile serial"
},
{
"name": "Unknown",
"type": "byte",
"size": 1,
"value": "0x00",
"description": "Unknown"
},
{
"name": "Lock Bits",
"type": "bitfield",
"size": 1,
"description": "Packed stat lock states. Bit layout: 00SSDDII where SS=Str, DD=Dex, II=Int",
"flags": [
"size": "Varies",
"fields": [],
"variants": [
{
"name": "Bonded Status (Type 0)",
"condition": "Type = 0: Pet bonding status",
"size": 11,
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xBF",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "11",
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "ushort",
"size": 2,
"value": "0x0019",
"description": "Extended Status subcommand"
},
{
"name": "Type",
"type": "byte",
"size": 1,
"value": "0x00",
"description": "Type 0 = Bonded Status"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Pet mobile serial"
},
{
"name": "Bonded",
"type": "bool",
"size": 1,
"description": "True if pet is bonded to owner"
}
],
"notes": "Sent when a pet's bonded status changes or when pet info is requested."
},
{
"name": "Stat Lock Info - Classic (Type 2)",
"condition": "Type = 2: Classic Client stat locks",
"size": 12,
"clientVersion": {
"classic": {}
},
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xBF",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "12",
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "ushort",
"size": 2,
"value": "0x0019",
"description": "Extended Status subcommand"
},
{
"name": "Type",
"type": "byte",
"size": 1,
"value": "0x02",
"description": "Type 2 = Stat Lock Info (Classic Client)"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Player mobile serial"
},
{
"name": "Unknown",
"type": "byte",
"size": 1,
"value": "0x00",
"description": "Unknown (always 0)"
},
{
"name": "Lock Bits",
"type": "bitfield",
"size": 1,
"description": "Packed stat lock states (00SSDDII)",
"flags": [
{
"bit": "5-4",
"name": "Str Lock",
"description": "Strength lock (value \u003c\u003c 4)"
"description": "Strength lock (value << 4)"
},
{
"bit": "3-2",
"name": "Dex Lock",
"description": "Dexterity lock (value \u003c\u003c 2)"
"description": "Dexterity lock (value << 2)"
},
{
"bit": "1-0",
"name": "Int Lock",
"description": "Intelligence lock (value \u003c\u003c 0)"
"description": "Intelligence lock (value << 0)"
}
],
"values": [
{
"value": 0,
"name": "Up",
"description": "Stat will increase when gains are available"
},
{
"value": 1,
"name": "Down",
"description": "Stat will decrease to allow other stats to increase"
},
{
"value": 2,
"name": "Locked",
"description": "Stat will not change"
}
],
"notes": "Formula: (StrLock \u003c\u003c 4) | (DexLock \u003c\u003c 2) | IntLock. Example: Str=Locked(2), Dex=Up(0), Int=Down(1) = 0b00100001 = 0x21"
}
],
"values": [
{
"value": 0,
"name": "Up",
"description": "Stat gains enabled"
},
{
"value": 1,
"name": "Down",
"description": "Stat decreases enabled"
},
{
"value": 2,
"name": "Locked",
"description": "Stat locked"
}
],
"notes": "Formula: (StrLock << 4) | (DexLock << 2) | IntLock"
}
]
},
{
"name": "Stat Lock Info - Enhanced (Type 5)",
"condition": "Type = 5: Enhanced Client stat locks",
"size": 12,
"clientVersion": {
"enhanced": {}
},
"fields": [
{
"name": "Packet ID",
"type": "byte",
"size": 1,
"value": "0xBF",
"description": "Packet identifier"
},
{
"name": "Length",
"type": "ushort",
"size": 2,
"value": "12",
"description": "Packet length"
},
{
"name": "Sub-Command",
"type": "ushort",
"size": 2,
"value": "0x0019",
"description": "Extended Status subcommand"
},
{
"name": "Type",
"type": "byte",
"size": 1,
"value": "0x05",
"description": "Type 5 = Stat Lock Info (Enhanced Client)"
},
{
"name": "Serial",
"type": "uint",
"size": 4,
"description": "Player mobile serial"
},
{
"name": "Unknown",
"type": "byte",
"size": 1,
"value": "0x00",
"description": "Unknown (always 0)"
},
{
"name": "Lock Bits",
"type": "bitfield",
"size": 1,
"description": "Packed stat lock states (00SSDDII)",
"flags": [
{
"bit": "5-4",
"name": "Str Lock",
"description": "Strength lock (value << 4)"
},
{
"bit": "3-2",
"name": "Dex Lock",
"description": "Dexterity lock (value << 2)"
},
{
"bit": "1-0",
"name": "Int Lock",
"description": "Intelligence lock (value << 0)"
}
],
"values": [
{
"value": 0,
"name": "Up",
"description": "Stat gains enabled"
},
{
"value": 1,
"name": "Down",
"description": "Stat decreases enabled"
},
{
"value": 2,
"name": "Locked",
"description": "Stat locked"
}
],
"notes": "Formula: (StrLock << 4) | (DexLock << 2) | IntLock"
}
],
"notes": "Enhanced Client uses Type 5 instead of Type 2"
}
],
"tags": ["Player", "Mobile"],
"notes": "The Type byte after the sub-command determines the packet structure. Type 0 is for pet bonding, Types 2/5 are for player stat locks (Classic/Enhanced Client respectively).",
"source": {
"file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs",
"line": 36

View file

@ -1,4 +1,4 @@
{
{
"category": "Secure Trade",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Targeting",
"packets": [
{
@ -79,7 +79,7 @@
"variants": [
{
"version": "pre-HighSeas",
"name": "Classic",
"name": "Pre-HighSeas (26 bytes)",
"size": 26,
"fields": [
{
@ -141,8 +141,8 @@
},
{
"version": "HighSeas+",
"name": "High Seas Extended",
"condition": "Client version \u003e= 7.0.9.0 (HighSeas)",
"name": "HighSeas / Enhanced (30 bytes)",
"condition": "Classic >= 7.0.9.0, or Enhanced Client (any version)",
"size": 30,
"fields": [
{
@ -210,7 +210,11 @@
}
],
"clientVersion": {
"feature": "HighSeas adds 4 bytes"
"classic": {
"min": "7.0.9.0"
},
"enhanced": {},
"notes": "HighSeas expansion adds 4 bytes. EC always uses 30-byte variant."
},
"source": {
"file": "Projects/Server/Network/Packets/OutgoingTargetPackets.cs",

View file

@ -1,4 +1,4 @@
{
{
"category": "Vendor",
"packets": [
{

View file

@ -1,4 +1,4 @@
{
{
"category": "Weapon Ability",
"packets": [
{

File diff suppressed because one or more lines are too long

View file

@ -84,6 +84,14 @@
background-position: right 0.75rem center;
padding-right: 2rem;
}
.client-badge {
font-size: 0.65rem;
padding: 1px 4px;
border-radius: 3px;
font-weight: 500;
}
.client-cc { background: rgba(59, 130, 246, 0.3); color: #93c5fd; }
.client-ec { background: rgba(168, 85, 247, 0.3); color: #d8b4fe; }
</style>
</head>
@ -147,6 +155,26 @@
<div id="tagFilter" class="hidden md:flex flex-wrap gap-1 max-h-32 overflow-y-auto">
<!-- Tags will be populated by JavaScript -->
</div>
<!-- Client Type Filter -->
<div class="flex items-center gap-2 mt-2">
<span class="text-gold-500/70 text-xs flex-shrink-0">Client:</span>
</div>
<div class="flex space-x-1 mt-1">
<button data-client="all" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-gold-500 text-modern-black font-medium">All</button>
<button data-client="classic" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-blue-400 border border-blue-500/50 hover:bg-blue-500/20">Classic</button>
<button data-client="enhanced" class="client-btn flex-1 px-2 py-1 text-xs rounded bg-modern-dark-black text-purple-400 border border-purple-500/50 hover:bg-purple-500/20">Enhanced</button>
</div>
<!-- Version Filter -->
<div class="mt-2">
<input
type="text"
id="versionInput"
placeholder="Version (e.g., 7.0.9.0)"
class="w-full bg-modern-dark-black text-gold-300 placeholder-gold-500/50 px-3 py-1.5 rounded border border-gold-500/30 focus:outline-none focus:border-gold-500 text-xs font-mono"
>
</div>
</div>
<!-- Packet List -->
@ -213,8 +241,11 @@
<!-- Client Version Requirements -->
<div id="clientVersionSection" class="bg-modern-black rounded-lg p-4 mb-6 border border-gold-500/20 hidden">
<h3 class="text-gold-500 font-medium mb-2">Client Version Requirements</h3>
<div id="clientVersionContent" class="text-gold-300/80 text-sm"></div>
<h3 class="text-gold-500 font-medium mb-3">Client Version Requirements</h3>
<div id="clientVersionContent" class="grid grid-cols-1 md:grid-cols-2 gap-3">
<!-- Populated by JavaScript -->
</div>
<div id="clientVersionNotes" class="mt-3 text-gold-500/70 text-sm italic hidden"></div>
</div>
<!-- Fields Table -->
@ -384,6 +415,16 @@
<div class="flex"><span class="font-mono text-gold-400 w-20 flex-shrink-0">packet</span><span>Embedded packet</span></div>
</div>
</div>
<!-- Client Indicators -->
<div class="bg-modern-dark-black rounded-lg p-3 border border-gold-500/10">
<h4 class="text-gold-400 font-medium mb-2">Client Indicators</h4>
<p class="text-gold-500/60 text-xs mb-2">Shown when a packet is client-specific</p>
<div class="space-y-1.5 text-gold-300/80">
<div class="flex items-center"><span class="client-badge client-cc w-12 text-center flex-shrink-0">CC</span><span class="ml-2">Classic Client only (2D)</span></div>
<div class="flex items-center"><span class="client-badge client-ec w-12 text-center flex-shrink-0">EC</span><span class="ml-2">Enhanced Client only (EC/KR)</span></div>
</div>
<p class="text-gold-500/60 text-xs mt-2">Packets without a badge support both clients.</p>
</div>
</div>
<div class="mt-4 text-xs text-gold-500/60">
<p><strong>Note:</strong> All multi-byte integers use Big Endian (network) byte order unless otherwise specified.</p>
@ -552,6 +593,8 @@ let currentFilter = 'all';
let selectedTags = new Set();
let currentSearch = '';
let selectedPacket = null;
let currentClientType = 'all';
let currentVersion = '';
// DOM elements
const searchInput = document.getElementById('searchInput');
@ -738,6 +781,81 @@ function getDirectionBgClass(direction) {
}
}
function getClientSupport(packet) {
const cv = packet.clientVersion;
if (!cv) return 'both';
const hasClassic = cv.classic !== undefined;
const hasEnhanced = cv.enhanced !== undefined;
if (hasClassic && hasEnhanced) return 'both';
if (hasClassic) return 'classic';
if (hasEnhanced) return 'enhanced';
return 'both';
}
function getClientBadge(packet) {
const support = getClientSupport(packet);
if (support === 'both') return '';
if (support === 'classic') return '<span class="client-badge client-cc">CC</span>';
if (support === 'enhanced') return '<span class="client-badge client-ec">EC</span>';
return '';
}
// Version parsing helper - handles "7.0.9.0", "5.0.0a", "66.x.x.x" formats
function parseVersion(v) {
if (!v) return null;
// Remove any trailing letters (like "5.0.0a" -> "5.0.0")
const cleaned = v.replace(/[a-z]$/i, '');
const parts = cleaned.split('.').map(part => {
if (part === 'x' || part === '*') return -1; // Wildcard marker
const num = parseInt(part, 10);
return isNaN(num) ? 0 : num;
});
// Pad to 4 parts
while (parts.length < 4) parts.push(0);
return parts.slice(0, 4);
}
// Compare two version arrays: returns -1, 0, or 1
function compareVersions(a, b) {
for (let i = 0; i < 4; i++) {
// Wildcards (-1) match anything
if (a[i] === -1 || b[i] === -1) continue;
if (a[i] < b[i]) return -1;
if (a[i] > b[i]) return 1;
}
return 0;
}
// Check if a version is within a client version range
function isVersionInRange(version, clientVersion, clientType) {
const v = parseVersion(version);
if (!v) return true; // Invalid version input, don't filter
// Check appropriate client type(s)
const typesToCheck = clientType === 'all'
? ['classic', 'enhanced'].filter(t => clientVersion[t])
: [clientType];
if (typesToCheck.length === 0) return true; // No version info for this type
return typesToCheck.some(type => {
const range = clientVersion[type];
if (!range) return false;
const min = range.min ? parseVersion(range.min) : [0, 0, 0, 0];
const max = range.max ? parseVersion(range.max) : [Infinity, Infinity, Infinity, Infinity];
// Handle wildcards in max (e.g., "7.0.8.x" means any 7.0.8.*)
for (let i = 0; i < 4; i++) {
if (max[i] === -1) max[i] = Infinity;
}
return compareVersions(v, min) >= 0 && compareVersions(v, max) <= 0;
});
}
// Filter packets
function getFilteredPackets() {
return packets.filter(p => {
@ -769,6 +887,21 @@ function getFilteredPackets() {
if (!matchId && !matchName && !matchDesc && !matchFields && !matchDecimal) return false;
}
// Client type filter - packets without clientVersion always pass (work with all versions)
if (currentClientType !== 'all' && p.clientVersion) {
const hasType = currentClientType === 'classic'
? p.clientVersion.classic
: p.clientVersion.enhanced;
if (!hasType) return false;
}
// Version filter (range check) - packets without clientVersion always pass
if (currentVersion && p.clientVersion) {
if (!isVersionInRange(currentVersion, p.clientVersion, currentClientType)) {
return false;
}
}
return true;
});
}
@ -816,6 +949,7 @@ function renderPacketList() {
>
<div class="flex items-center space-x-2">
<span class="font-mono text-sm ${getDirectionClass(p.direction)}">${displayId}</span>
${getClientBadge(p)}
<span class="text-gold-300/90 text-sm truncate">${p.name}</span>
</div>
<div class="flex flex-wrap gap-1 mt-0.5">
@ -1031,14 +1165,54 @@ function selectPacket(packet) {
// Client version
const versionSection = document.getElementById('clientVersionSection');
const versionContent = document.getElementById('clientVersionContent');
const versionNotes = document.getElementById('clientVersionNotes');
if (packet.clientVersion) {
versionSection.classList.remove('hidden');
let versionText = '';
if (packet.clientVersion.min) versionText += `Min: ${packet.clientVersion.min} `;
if (packet.clientVersion.max) versionText += `Max: ${packet.clientVersion.max} `;
if (packet.clientVersion.feature) versionText += `Feature: ${packet.clientVersion.feature} `;
if (packet.clientVersion.notes) versionText += `<br>${packet.clientVersion.notes}`;
versionContent.innerHTML = versionText || 'Version-specific behavior';
let html = '';
// Classic Client
if (packet.clientVersion.classic) {
const c = packet.clientVersion.classic;
html += `
<div class="bg-modern-dark-black rounded p-3 border border-gold-500/10">
<div class="flex items-center gap-2 mb-2">
<span class="px-2 py-0.5 bg-blue-500/20 text-blue-400 rounded text-xs font-medium">Classic</span>
</div>
<div class="text-sm space-y-1">
${c.min ? `<div><span class="text-gold-500/70">Min:</span> <span class="font-mono text-gold-300">${c.min}</span></div>` : ''}
${c.max ? `<div><span class="text-gold-500/70">Max:</span> <span class="font-mono text-gold-300">${c.max}</span></div>` : ''}
${!c.min && !c.max ? `<div class="text-gold-500/50">All versions</div>` : ''}
</div>
</div>
`;
}
// Enhanced Client
if (packet.clientVersion.enhanced) {
const e = packet.clientVersion.enhanced;
html += `
<div class="bg-modern-dark-black rounded p-3 border border-gold-500/10">
<div class="flex items-center gap-2 mb-2">
<span class="px-2 py-0.5 bg-purple-500/20 text-purple-400 rounded text-xs font-medium">Enhanced</span>
</div>
<div class="text-sm space-y-1">
${e.min ? `<div><span class="text-gold-500/70">Min:</span> <span class="font-mono text-gold-300">${e.min}</span></div>` : ''}
${e.max ? `<div><span class="text-gold-500/70">Max:</span> <span class="font-mono text-gold-300">${e.max}</span></div>` : ''}
${!e.min && !e.max ? `<div class="text-gold-500/50">All versions</div>` : ''}
</div>
</div>
`;
}
versionContent.innerHTML = html;
// Notes
if (packet.clientVersion.notes) {
versionNotes.classList.remove('hidden');
versionNotes.textContent = packet.clientVersion.notes;
} else {
versionNotes.classList.add('hidden');
}
} else {
versionSection.classList.add('hidden');
}
@ -1125,10 +1299,14 @@ function selectPacket(packet) {
const directionBadge = r.direction ?
`<span class="px-1.5 py-0.5 rounded text-xs font-medium uppercase ${getDirectionBgClass(r.direction)} text-white">${r.direction}</span>` : '';
const idColorClass = relatedPacket ? getDirectionClass(relatedPacket.direction) : 'text-white';
const clientBadge = relatedPacket ? getClientBadge(relatedPacket) : '';
return `
<div class="flex items-center justify-between bg-modern-black rounded-lg p-3 border border-gold-500/20 cursor-pointer hover:border-gold-500/40 transition-colors related-packet" data-id="${r.id}" data-direction="${r.direction || ''}">
<div class="flex items-center space-x-3">
<span class="font-mono text-white">${r.id}</span>
<span class="font-mono ${idColorClass}">${r.id}</span>
${clientBadge}
${directionBadge}
<span class="text-gold-300/90">${relatedPacket?.name || 'Unknown'}</span>
</div>
@ -1217,6 +1395,17 @@ function selectPacket(packet) {
// Show condition/description below header for all variants (not inline)
const hasCondition = v.condition && !v.subVariants;
// Build client version info
let clientVersionHtml = '';
if (v.clientVersion) {
const parts = [];
if (v.clientVersion.min) parts.push(`Min: ${v.clientVersion.min}`);
if (v.clientVersion.max) parts.push(`Max: ${v.clientVersion.max}`);
if (parts.length > 0) {
clientVersionHtml = `<span class="text-gold-400/70 text-xs ml-3">[${parts.join(', ')}]</span>`;
}
}
return `
<div id="${id}" class="bg-modern-black rounded-lg border border-gold-500/20 overflow-hidden">
<div class="bg-gold-500/10 px-4 py-2 flex items-center justify-between">
@ -1224,12 +1413,14 @@ function selectPacket(packet) {
<span class="text-gold-500 font-medium">${v.name || 'Variant'}</span>
${directionBadge}
${v.version ? `<span class="text-gold-500/70 ml-2 text-sm">(${v.version})</span>` : ''}
${clientVersionHtml}
</div>
<div class="flex items-center space-x-3 text-sm flex-shrink-0">
${v.size ? `<span class="text-gold-500/70">Size: <span class="text-white font-mono">${typeof v.size === 'number' ? v.size + ' bytes' : v.size}</span></span>` : ''}
</div>
</div>
${hasCondition ? `<div class="px-4 py-2 text-gold-300/80 text-sm border-b border-gold-500/10">${v.condition}</div>` : ''}
${v.notes ? `<div class="px-4 py-2 text-gold-500/70 text-xs italic border-b border-gold-500/10">${v.notes}</div>` : ''}
${content}
</div>
`;
@ -1455,15 +1646,20 @@ function selectPacket(packet) {
</div>
` : '';
// Build tags HTML if command has tags
const tagsHtml = cmd.tags && cmd.tags.length > 0 ?
cmd.tags.map(tag => `<span class="px-1.5 py-0.5 rounded text-xs font-medium bg-purple-500/20 text-purple-400 ml-2">${tag}</span>`).join('') : '';
return `
<div class="py-3 px-4">
<div class="flex items-start justify-between gap-4">
<div>
<span class="font-mono text-gold-400 font-medium">${cmd.name}</span>
<span class="font-mono text-gold-400 font-medium">${cmd.name}</span>${tagsHtml}
<span class="text-gold-300/70 ml-3">${cmd.description || ''}</span>
</div>
</div>
<div class="font-mono text-xs text-gold-500/80 mt-1">${syntax}</div>
${cmd.notes ? `<div class="text-gold-500/60 text-xs mt-1 italic">${cmd.notes}</div>` : ''}
${argsHtml}
</div>
`;
@ -1564,6 +1760,42 @@ searchInput.addEventListener('input', (e) => {
}, 150);
});
// Client type button handlers
document.querySelectorAll('.client-btn').forEach(btn => {
btn.addEventListener('click', () => {
currentClientType = btn.dataset.client;
// Update button styles
document.querySelectorAll('.client-btn').forEach(b => {
const isActive = b.dataset.client === currentClientType;
if (b.dataset.client === 'all') {
b.classList.toggle('bg-gold-500', isActive);
b.classList.toggle('text-modern-black', isActive);
b.classList.toggle('bg-modern-dark-black', !isActive);
b.classList.toggle('text-gold-500', !isActive);
} else if (b.dataset.client === 'classic') {
b.classList.toggle('bg-blue-500/20', isActive);
b.classList.toggle('bg-modern-dark-black', !isActive);
} else if (b.dataset.client === 'enhanced') {
b.classList.toggle('bg-purple-500/20', isActive);
b.classList.toggle('bg-modern-dark-black', !isActive);
}
});
renderPacketList();
});
});
// Version input handler
const versionInput = document.getElementById('versionInput');
let versionTimeout;
versionInput.addEventListener('input', (e) => {
clearTimeout(versionTimeout);
versionTimeout = setTimeout(() => {
currentVersion = e.target.value.trim();
renderPacketList();
}, 300);
});
// Keyboard navigation
document.addEventListener('keydown', (e) => {