From 3e8f14a0ac4342aef67f3a73022c198620628099 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sat, 31 Jan 2026 10:20:48 -0800 Subject: [PATCH] chore: Adds missing packets and cleans up packets.html (#2321) --- docs/packets/incoming/account.json | 286 +++- docs/packets/incoming/assistant.json | 2 +- docs/packets/incoming/book.json | 2 +- docs/packets/incoming/chat.json | 2 +- docs/packets/incoming/encoded.json | 12 +- docs/packets/incoming/entity.json | 2 +- docs/packets/incoming/extended.json | 36 +- docs/packets/incoming/freeshard.json | 134 ++ docs/packets/incoming/gump.json | 116 ++ docs/packets/incoming/hardware.json | 188 +++ docs/packets/incoming/house.json | 37 + docs/packets/incoming/items.json | 14 +- docs/packets/incoming/map.json | 2 +- docs/packets/incoming/message.json | 2 +- docs/packets/incoming/mobile.json | 2 +- docs/packets/incoming/movement.json | 2 +- docs/packets/incoming/player.json | 2 +- docs/packets/incoming/store.json | 32 + docs/packets/incoming/targeting.json | 2 +- docs/packets/incoming/vendor.json | 2 +- docs/packets/outgoing/account.json | 6 +- docs/packets/outgoing/arrow.json | 8 +- docs/packets/outgoing/assistant.json | 2 +- docs/packets/outgoing/boat.json | 8 +- docs/packets/outgoing/book.json | 2 +- docs/packets/outgoing/bufficon.json | 9 +- docs/packets/outgoing/bulletinboard.json | 2 +- docs/packets/outgoing/chat.json | 2 +- docs/packets/outgoing/combat.json | 2 +- docs/packets/outgoing/container.json | 33 +- docs/packets/outgoing/contextmenu.json | 8 +- docs/packets/outgoing/damage.json | 19 +- docs/packets/outgoing/effects.json | 2 +- docs/packets/outgoing/entity.json | 16 +- docs/packets/outgoing/equipment.json | 2 +- docs/packets/outgoing/freeshard.json | 70 + docs/packets/outgoing/gump.json | 31 +- docs/packets/outgoing/house.json | 9 +- docs/packets/outgoing/items.json | 6 +- docs/packets/outgoing/light.json | 2 +- docs/packets/outgoing/mahjong.json | 2 +- docs/packets/outgoing/map.json | 9 +- docs/packets/outgoing/menu.json | 2 +- docs/packets/outgoing/message.json | 2 +- docs/packets/outgoing/mobile.json | 517 ++++++- docs/packets/outgoing/movement.json | 2 +- docs/packets/outgoing/party.json | 2 +- docs/packets/outgoing/player.json | 304 +++- docs/packets/outgoing/securetrade.json | 2 +- docs/packets/outgoing/targeting.json | 14 +- docs/packets/outgoing/vendor.json | 2 +- docs/packets/outgoing/weaponability.json | 2 +- docs/packets/packets.html | 1679 ---------------------- docs/packets/template.html | 252 +++- 54 files changed, 1976 insertions(+), 1931 deletions(-) create mode 100644 docs/packets/incoming/freeshard.json create mode 100644 docs/packets/incoming/gump.json create mode 100644 docs/packets/incoming/hardware.json create mode 100644 docs/packets/incoming/house.json create mode 100644 docs/packets/incoming/store.json create mode 100644 docs/packets/outgoing/freeshard.json delete mode 100644 docs/packets/packets.html diff --git a/docs/packets/incoming/account.json b/docs/packets/incoming/account.json index b63640500..410864d6d 100644 --- a/docs/packets/incoming/account.json +++ b/docs/packets/incoming/account.json @@ -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." } ] } diff --git a/docs/packets/incoming/assistant.json b/docs/packets/incoming/assistant.json index 4af31ea9b..f7d83d658 100644 --- a/docs/packets/incoming/assistant.json +++ b/docs/packets/incoming/assistant.json @@ -1,4 +1,4 @@ -{ +{ "category": "Assistant", "packets": [ { diff --git a/docs/packets/incoming/book.json b/docs/packets/incoming/book.json index f75f7da55..7a8078c18 100644 --- a/docs/packets/incoming/book.json +++ b/docs/packets/incoming/book.json @@ -1,4 +1,4 @@ -{ +{ "category": "Book", "packets": [ { diff --git a/docs/packets/incoming/chat.json b/docs/packets/incoming/chat.json index 8bbe1a998..a62d2e9ed 100644 --- a/docs/packets/incoming/chat.json +++ b/docs/packets/incoming/chat.json @@ -1,4 +1,4 @@ -{ +{ "category": "Chat", "packets": [ { diff --git a/docs/packets/incoming/encoded.json b/docs/packets/incoming/encoded.json index 551f582e3..3b5cad9db 100644 --- a/docs/packets/incoming/encoded.json +++ b/docs/packets/incoming/encoded.json @@ -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": { diff --git a/docs/packets/incoming/entity.json b/docs/packets/incoming/entity.json index f5e62ab93..52f2d32b4 100644 --- a/docs/packets/incoming/entity.json +++ b/docs/packets/incoming/entity.json @@ -1,4 +1,4 @@ -{ +{ "category": "Item", "tags": ["Mobile"], "packets": [ diff --git a/docs/packets/incoming/extended.json b/docs/packets/incoming/extended.json index a302395d8..a4b531bc5 100644 --- a/docs/packets/incoming/extended.json +++ b/docs/packets/incoming/extended.json @@ -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", diff --git a/docs/packets/incoming/freeshard.json b/docs/packets/incoming/freeshard.json new file mode 100644 index 000000000..83e50ccd4 --- /dev/null +++ b/docs/packets/incoming/freeshard.json @@ -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 + } + } + ] +} diff --git a/docs/packets/incoming/gump.json b/docs/packets/incoming/gump.json new file mode 100644 index 000000000..932baa998 --- /dev/null +++ b/docs/packets/incoming/gump.json @@ -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 + } + } + ] +} diff --git a/docs/packets/incoming/hardware.json b/docs/packets/incoming/hardware.json new file mode 100644 index 000000000..81bb40be7 --- /dev/null +++ b/docs/packets/incoming/hardware.json @@ -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." + } + ] +} diff --git a/docs/packets/incoming/house.json b/docs/packets/incoming/house.json new file mode 100644 index 000000000..bd7aa8e5a --- /dev/null +++ b/docs/packets/incoming/house.json @@ -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." + } + ] +} diff --git a/docs/packets/incoming/items.json b/docs/packets/incoming/items.json index da8962d88..27fc35703 100644 --- a/docs/packets/incoming/items.json +++ b/docs/packets/incoming/items.json @@ -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 diff --git a/docs/packets/incoming/map.json b/docs/packets/incoming/map.json index 8f436c546..2e8565423 100644 --- a/docs/packets/incoming/map.json +++ b/docs/packets/incoming/map.json @@ -1,4 +1,4 @@ -{ +{ "category": "Map", "packets": [ { diff --git a/docs/packets/incoming/message.json b/docs/packets/incoming/message.json index 8014f3c0b..4dc5fc429 100644 --- a/docs/packets/incoming/message.json +++ b/docs/packets/incoming/message.json @@ -1,4 +1,4 @@ -{ +{ "category": "Message", "packets": [ { diff --git a/docs/packets/incoming/mobile.json b/docs/packets/incoming/mobile.json index c1860be0a..9cea2c944 100644 --- a/docs/packets/incoming/mobile.json +++ b/docs/packets/incoming/mobile.json @@ -1,4 +1,4 @@ -{ +{ "category": "Mobile", "packets": [ { diff --git a/docs/packets/incoming/movement.json b/docs/packets/incoming/movement.json index 1898a7675..d776d3382 100644 --- a/docs/packets/incoming/movement.json +++ b/docs/packets/incoming/movement.json @@ -1,4 +1,4 @@ -{ +{ "category": "Movement", "packets": [ { diff --git a/docs/packets/incoming/player.json b/docs/packets/incoming/player.json index c21245b04..4596bb776 100644 --- a/docs/packets/incoming/player.json +++ b/docs/packets/incoming/player.json @@ -1,4 +1,4 @@ -{ +{ "category": "Player", "packets": [ { diff --git a/docs/packets/incoming/store.json b/docs/packets/incoming/store.json new file mode 100644 index 000000000..04ec54c22 --- /dev/null +++ b/docs/packets/incoming/store.json @@ -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." + } + ] +} diff --git a/docs/packets/incoming/targeting.json b/docs/packets/incoming/targeting.json index 9b56a84e4..ca9470029 100644 --- a/docs/packets/incoming/targeting.json +++ b/docs/packets/incoming/targeting.json @@ -1,4 +1,4 @@ -{ +{ "category": "Targeting", "packets": [ { diff --git a/docs/packets/incoming/vendor.json b/docs/packets/incoming/vendor.json index 48e654674..ee54fa693 100644 --- a/docs/packets/incoming/vendor.json +++ b/docs/packets/incoming/vendor.json @@ -1,4 +1,4 @@ -{ +{ "category": "Vendor", "packets": [ { diff --git a/docs/packets/outgoing/account.json b/docs/packets/outgoing/account.json index b7f5d7274..7b0fda674 100644 --- a/docs/packets/outgoing/account.json +++ b/docs/packets/outgoing/account.json @@ -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", diff --git a/docs/packets/outgoing/arrow.json b/docs/packets/outgoing/arrow.json index 834134715..9ce0d935a 100644 --- a/docs/packets/outgoing/arrow.json +++ b/docs/packets/outgoing/arrow.json @@ -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", diff --git a/docs/packets/outgoing/assistant.json b/docs/packets/outgoing/assistant.json index 634563aac..1fb05e6ea 100644 --- a/docs/packets/outgoing/assistant.json +++ b/docs/packets/outgoing/assistant.json @@ -1,4 +1,4 @@ -{ +{ "category": "Assistant", "packets": [ { diff --git a/docs/packets/outgoing/boat.json b/docs/packets/outgoing/boat.json index 25708cbc8..d295510d1 100644 --- a/docs/packets/outgoing/boat.json +++ b/docs/packets/outgoing/boat.json @@ -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", diff --git a/docs/packets/outgoing/book.json b/docs/packets/outgoing/book.json index 34e3addd5..6f89e299b 100644 --- a/docs/packets/outgoing/book.json +++ b/docs/packets/outgoing/book.json @@ -1,4 +1,4 @@ -{ +{ "category": "Book", "packets": [ { diff --git a/docs/packets/outgoing/bufficon.json b/docs/packets/outgoing/bufficon.json index 3aa402595..a4f2dbf7d 100644 --- a/docs/packets/outgoing/bufficon.json +++ b/docs/packets/outgoing/bufficon.json @@ -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", diff --git a/docs/packets/outgoing/bulletinboard.json b/docs/packets/outgoing/bulletinboard.json index 9225a639f..07073b263 100644 --- a/docs/packets/outgoing/bulletinboard.json +++ b/docs/packets/outgoing/bulletinboard.json @@ -1,4 +1,4 @@ -{ +{ "category": "Bulletin Board", "packets": [ { diff --git a/docs/packets/outgoing/chat.json b/docs/packets/outgoing/chat.json index 3dec3964c..87819fb1b 100644 --- a/docs/packets/outgoing/chat.json +++ b/docs/packets/outgoing/chat.json @@ -1,4 +1,4 @@ -{ +{ "category": "Chat", "packets": [ { diff --git a/docs/packets/outgoing/combat.json b/docs/packets/outgoing/combat.json index 99dbff07e..c5d09cef6 100644 --- a/docs/packets/outgoing/combat.json +++ b/docs/packets/outgoing/combat.json @@ -1,4 +1,4 @@ -{ +{ "category": "Combat", "packets": [ { diff --git a/docs/packets/outgoing/container.json b/docs/packets/outgoing/container.json index bb9a2c078..3f8f7b9f1 100644 --- a/docs/packets/outgoing/container.json +++ b/docs/packets/outgoing/container.json @@ -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": { diff --git a/docs/packets/outgoing/contextmenu.json b/docs/packets/outgoing/contextmenu.json index e299970ef..82456e189 100644 --- a/docs/packets/outgoing/contextmenu.json +++ b/docs/packets/outgoing/contextmenu.json @@ -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", diff --git a/docs/packets/outgoing/damage.json b/docs/packets/outgoing/damage.json index 595710aab..24f927fbe 100644 --- a/docs/packets/outgoing/damage.json +++ b/docs/packets/outgoing/damage.json @@ -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 diff --git a/docs/packets/outgoing/effects.json b/docs/packets/outgoing/effects.json index 2a9710620..47af65187 100644 --- a/docs/packets/outgoing/effects.json +++ b/docs/packets/outgoing/effects.json @@ -1,4 +1,4 @@ -{ +{ "category": "Effects", "packets": [ { diff --git a/docs/packets/outgoing/entity.json b/docs/packets/outgoing/entity.json index aa089b6d4..b0627f7e6 100644 --- a/docs/packets/outgoing/entity.json +++ b/docs/packets/outgoing/entity.json @@ -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", diff --git a/docs/packets/outgoing/equipment.json b/docs/packets/outgoing/equipment.json index 64d32d143..a86595f27 100644 --- a/docs/packets/outgoing/equipment.json +++ b/docs/packets/outgoing/equipment.json @@ -1,4 +1,4 @@ -{ +{ "category": "Equipment", "packets": [ { diff --git a/docs/packets/outgoing/freeshard.json b/docs/packets/outgoing/freeshard.json new file mode 100644 index 000000000..38bb5a6af --- /dev/null +++ b/docs/packets/outgoing/freeshard.json @@ -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 + } + } + ] +} diff --git a/docs/packets/outgoing/gump.json b/docs/packets/outgoing/gump.json index ba24dfebc..21b338ae9 100644 --- a/docs/packets/outgoing/gump.json +++ b/docs/packets/outgoing/gump.json @@ -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": { diff --git a/docs/packets/outgoing/house.json b/docs/packets/outgoing/house.json index 071e7fbe8..3fff90eed 100644 --- a/docs/packets/outgoing/house.json +++ b/docs/packets/outgoing/house.json @@ -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", diff --git a/docs/packets/outgoing/items.json b/docs/packets/outgoing/items.json index 133f98a07..2c9f6e0f7 100644 --- a/docs/packets/outgoing/items.json +++ b/docs/packets/outgoing/items.json @@ -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": { diff --git a/docs/packets/outgoing/light.json b/docs/packets/outgoing/light.json index ea318024b..0958046b4 100644 --- a/docs/packets/outgoing/light.json +++ b/docs/packets/outgoing/light.json @@ -1,4 +1,4 @@ -{ +{ "category": "Light", "packets": [ { diff --git a/docs/packets/outgoing/mahjong.json b/docs/packets/outgoing/mahjong.json index e3de6cb1f..5b9f3b9a9 100644 --- a/docs/packets/outgoing/mahjong.json +++ b/docs/packets/outgoing/mahjong.json @@ -1,4 +1,4 @@ -{ +{ "category": "Mahjong", "packets": [ { diff --git a/docs/packets/outgoing/map.json b/docs/packets/outgoing/map.json index eff31a607..e9e77376b 100644 --- a/docs/packets/outgoing/map.json +++ b/docs/packets/outgoing/map.json @@ -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", diff --git a/docs/packets/outgoing/menu.json b/docs/packets/outgoing/menu.json index 57d330ce6..e69969a11 100644 --- a/docs/packets/outgoing/menu.json +++ b/docs/packets/outgoing/menu.json @@ -1,4 +1,4 @@ -{ +{ "category": "Menu", "packets": [ { diff --git a/docs/packets/outgoing/message.json b/docs/packets/outgoing/message.json index 7369cbd50..df69402d9 100644 --- a/docs/packets/outgoing/message.json +++ b/docs/packets/outgoing/message.json @@ -1,4 +1,4 @@ -{ +{ "category": "Message", "packets": [ { diff --git a/docs/packets/outgoing/mobile.json b/docs/packets/outgoing/mobile.json index 6c49fcb99..581f82c1c 100644 --- a/docs/packets/outgoing/mobile.json +++ b/docs/packets/outgoing/mobile.json @@ -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 - } } ] } \ No newline at end of file diff --git a/docs/packets/outgoing/movement.json b/docs/packets/outgoing/movement.json index 79153d476..8d7632686 100644 --- a/docs/packets/outgoing/movement.json +++ b/docs/packets/outgoing/movement.json @@ -1,4 +1,4 @@ -{ +{ "category": "Movement", "packets": [ { diff --git a/docs/packets/outgoing/party.json b/docs/packets/outgoing/party.json index 0a173d9e4..e62878ddb 100644 --- a/docs/packets/outgoing/party.json +++ b/docs/packets/outgoing/party.json @@ -1,4 +1,4 @@ -{ +{ "category": "Party", "packets": [ { diff --git a/docs/packets/outgoing/player.json b/docs/packets/outgoing/player.json index 921a59323..cf42eed14 100644 --- a/docs/packets/outgoing/player.json +++ b/docs/packets/outgoing/player.json @@ -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 diff --git a/docs/packets/outgoing/securetrade.json b/docs/packets/outgoing/securetrade.json index 1a0e1d9e4..46d046f2a 100644 --- a/docs/packets/outgoing/securetrade.json +++ b/docs/packets/outgoing/securetrade.json @@ -1,4 +1,4 @@ -{ +{ "category": "Secure Trade", "packets": [ { diff --git a/docs/packets/outgoing/targeting.json b/docs/packets/outgoing/targeting.json index 4e6fd478f..e6e50fefa 100644 --- a/docs/packets/outgoing/targeting.json +++ b/docs/packets/outgoing/targeting.json @@ -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", diff --git a/docs/packets/outgoing/vendor.json b/docs/packets/outgoing/vendor.json index 2691f93a7..5c55b7f0e 100644 --- a/docs/packets/outgoing/vendor.json +++ b/docs/packets/outgoing/vendor.json @@ -1,4 +1,4 @@ -{ +{ "category": "Vendor", "packets": [ { diff --git a/docs/packets/outgoing/weaponability.json b/docs/packets/outgoing/weaponability.json index 3c54691c3..79f3ce907 100644 --- a/docs/packets/outgoing/weaponability.json +++ b/docs/packets/outgoing/weaponability.json @@ -1,4 +1,4 @@ -{ +{ "category": "Weapon Ability", "packets": [ { diff --git a/docs/packets/packets.html b/docs/packets/packets.html deleted file mode 100644 index 067c88b8d..000000000 --- a/docs/packets/packets.html +++ /dev/null @@ -1,1679 +0,0 @@ - - - - - - - - - ModernUO Packet Documentation - - - - - - - -
- -
-
-
- -
-

- Packet Documentation - -

- -
-
-
- - -
-
-
- - -
- - - - - - - -
-
- - - - -
-
📦
-

Select a Packet

-

Choose a packet from the list to view its documentation.

-

Use the search box to find packets by ID (0x02), name, or field names.

-
- - - -
-
-
-
- - - - - - - - - - - diff --git a/docs/packets/template.html b/docs/packets/template.html index f7620def7..a97b51649 100644 --- a/docs/packets/template.html +++ b/docs/packets/template.html @@ -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; } @@ -147,6 +155,26 @@ + + +
+ Client: +
+
+ + + +
+ + +
+ +
@@ -213,8 +241,11 @@ @@ -384,6 +415,16 @@
packetEmbedded packet
+ +
+

Client Indicators

+

Shown when a packet is client-specific

+
+
CCClassic Client only (2D)
+
ECEnhanced Client only (EC/KR)
+
+

Packets without a badge support both clients.

+

Note: All multi-byte integers use Big Endian (network) byte order unless otherwise specified.

@@ -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 'CC'; + if (support === 'enhanced') return 'EC'; + 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() { >
${displayId} + ${getClientBadge(p)} ${p.name}
@@ -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 += `
${packet.clientVersion.notes}`; - versionContent.innerHTML = versionText || 'Version-specific behavior'; + let html = ''; + + // Classic Client + if (packet.clientVersion.classic) { + const c = packet.clientVersion.classic; + html += ` +
+
+ Classic +
+
+ ${c.min ? `
Min: ${c.min}
` : ''} + ${c.max ? `
Max: ${c.max}
` : ''} + ${!c.min && !c.max ? `
All versions
` : ''} +
+
+ `; + } + + // Enhanced Client + if (packet.clientVersion.enhanced) { + const e = packet.clientVersion.enhanced; + html += ` +
+
+ Enhanced +
+
+ ${e.min ? `
Min: ${e.min}
` : ''} + ${e.max ? `
Max: ${e.max}
` : ''} + ${!e.min && !e.max ? `
All versions
` : ''} +
+
+ `; + } + + 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 ? `${r.direction}` : ''; + const idColorClass = relatedPacket ? getDirectionClass(relatedPacket.direction) : 'text-white'; + const clientBadge = relatedPacket ? getClientBadge(relatedPacket) : ''; + return ` `; @@ -1455,15 +1646,20 @@ function selectPacket(packet) {
` : ''; + // Build tags HTML if command has tags + const tagsHtml = cmd.tags && cmd.tags.length > 0 ? + cmd.tags.map(tag => `${tag}`).join('') : ''; + return `
- ${cmd.name} + ${cmd.name}${tagsHtml} ${cmd.description || ''}
${syntax}
+ ${cmd.notes ? `
${cmd.notes}
` : ''} ${argsHtml}
`; @@ -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) => {