diff --git a/.github/workflows/update-docs.yml b/.github/workflows/update-docs.yml index 3595a112a..c9a71f039 100644 --- a/.github/workflows/update-docs.yml +++ b/.github/workflows/update-docs.yml @@ -10,18 +10,31 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: 3.x - - run: pip install mkdocs-material - - run: mkdocs gh-deploy --force - - name: Extract commands web file + + - name: Install mkdocs-material + run: pip install mkdocs-material + + - name: Build mkdocs site + run: mkdocs build --strict + + - name: Build packets documentation + shell: pwsh + run: ./docs/tools/build-packets.ps1 + + - name: Copy commands and packets to site run: | - 7z x ./docs/commands/commands.7z -o./docs/commands - rm ./docs/commands/commands.7z - - name: Deploy commands file + cp ./docs/commands/commands.html ./site/ + cp ./docs/packets/packets.html ./site/ + + - name: Deploy to GitHub Pages uses: JamesIves/github-pages-deploy-action@v4 with: - folder: ./docs/commands - clean: false - force: false + folder: ./site + branch: gh-pages + clean: true + clean-exclude: | + .nojekyll diff --git a/Distribution/Data/commands.html b/Distribution/Data/commands/template.html similarity index 100% rename from Distribution/Data/commands.html rename to Distribution/Data/commands/template.html diff --git a/Projects/Server/Network/Packets/OutgoingPlayerPackets.cs b/Projects/Server/Network/Packets/OutgoingPlayerPackets.cs index b05a43940..5c5039345 100644 --- a/Projects/Server/Network/Packets/OutgoingPlayerPackets.cs +++ b/Projects/Server/Network/Packets/OutgoingPlayerPackets.cs @@ -56,12 +56,10 @@ public static class OutgoingPlayerPackets } [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SendChangeUpdateRange(this NetState ns, byte range) => - ns?.Send(stackalloc byte[] { 0xC8, range }); + public static void SendChangeUpdateRange(this NetState ns, byte range) => ns?.Send(stackalloc byte[] { 0xC8, range }); [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void SendDeathStatus(this NetState ns) => - ns?.Send(stackalloc byte[] { 0x2C, 2 }); + public static void SendDeathStatus(this NetState ns) => ns?.Send(stackalloc byte[] { 0x2C, 2 }); public static void SendDisplayProfile(this NetState ns, Serial m, string header, string body, string footer) { diff --git a/Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs b/Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs index ca4d0e65b..473e63f6c 100644 --- a/Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs +++ b/Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs @@ -29,9 +29,7 @@ public enum TradeFlag : byte public static class OutgoingSecureTradePackets { - public static void SendDisplaySecureTrade( - this NetState ns, Mobile them, Container first, Container second, string name - ) + public static void SendDisplaySecureTrade(this NetState ns, Mobile them, Container first, Container second, string name) { if (ns.CannotSendPackets()) { diff --git a/Projects/UOContent/Commands/GenCommands.cs b/Projects/UOContent/Commands/GenCommands.cs index 0892e1539..95a606c7f 100644 --- a/Projects/UOContent/Commands/GenCommands.cs +++ b/Projects/UOContent/Commands/GenCommands.cs @@ -57,15 +57,18 @@ public static class GenCommands options ); - var template = File.ReadAllText(Path.Combine(Core.BaseDirectory, "Data", "commands.html")) + // Template is in Distribution/Data/commands + var templatePath = Path.Combine(Core.BaseDirectory, "Data", "commands", "template.html"); + + var template = File.ReadAllText(templatePath) .Replace("", commandsJson.EscapeHtml()) .Replace("", modifiersJson.EscapeHtml()); - // Write the new file to the web folder + // Output to Distribution/web folder (typically ignored by servers for external systems) var webFolder = Path.Combine(Core.BaseDirectory, "web"); - PathUtility.EnsureDirectory(webFolder); - var webPath = Path.Combine(webFolder, "commands.html"); - File.WriteAllText(webPath, template, Encoding.UTF8); - e.Mobile.SendMessage($"Commands webpage generated at {webPath}."); + Directory.CreateDirectory(webFolder); + var outputPath = Path.Combine(webFolder, "commands.html"); + File.WriteAllText(outputPath, template, Encoding.UTF8); + e.Mobile.SendMessage($"Commands webpage generated at {outputPath}."); } } diff --git a/docs/commands/commands.7z b/docs/commands/commands.7z deleted file mode 100644 index 6db187201..000000000 Binary files a/docs/commands/commands.7z and /dev/null differ diff --git a/docs/commands/commands.html b/docs/commands/commands.html new file mode 100644 index 000000000..cce8ae7ce --- /dev/null +++ b/docs/commands/commands.html @@ -0,0 +1,2619 @@ + + + + + + + + + ModernUO Commands + + + + + + +
+
+
+ +
+ +
+ +

ModernUO Commands

+ +
    + +
+ +
+ +
+
+
+
+ + + + + + + diff --git a/docs/packets/incoming/account.json b/docs/packets/incoming/account.json new file mode 100644 index 000000000..b63640500 --- /dev/null +++ b/docs/packets/incoming/account.json @@ -0,0 +1,817 @@ +{ + "category": "Account", + "packets": [ + { + "id": "0x80", + "name": "Account Login", + "description": "Initial login request sent to the login server. Contains account credentials for authentication.", + "direction": "incoming", + "isDynamic": false, + "size": 62, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x80", + "description": "Packet identifier" + }, + { + "name": "Username", + "type": "ascii", + "size": 30, + "description": "Account username (null-terminated)" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Account password (null-terminated)" + }, + { + "name": "Next Login Key", + "type": "byte", + "size": 1, + "description": "Next login key" + } + ], + "related": [ + { + "id": "0x82", + "relationship": "rej", + "note": "Sent if login fails" + }, + { + "id": "0xA8", + "relationship": "ack", + "note": "Sent if login succeeds (server list)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 439 + } + }, + { + "id": "0x91", + "name": "Game Login", + "description": "Login request sent to the game server after selecting a shard from the server list.", + "direction": "incoming", + "isDynamic": false, + "size": 65, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x91", + "description": "Packet identifier" + }, + { + "name": "Auth ID", + "type": "int", + "size": 4, + "description": "Authentication ID from PlayServerAck (0x8C)" + }, + { + "name": "Username", + "type": "ascii", + "size": 30, + "description": "Account username" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Account password" + } + ], + "related": [ + { + "id": "0xA9", + "relationship": "response", + "note": "Character list sent on success" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 345 + } + }, + { + "id": "0x5D", + "name": "Play Character", + "description": "Request to enter the world with a selected character from the character list.", + "direction": "incoming", + "isDynamic": false, + "size": 73, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x5D", + "description": "Packet identifier" + }, + { + "name": "Pattern", + "type": "uint", + "size": 4, + "value": "0xEDEDEDED", + "description": "Fixed pattern" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name (unused)" + }, + { + "name": "Unknown", + "type": "byte[2]", + "size": 2, + "description": "Unknown" + }, + { + "name": "Flags", + "type": "int", + "size": 4, + "description": "Client flags" + }, + { + "name": "Unknown2", + "type": "byte[24]", + "size": 24, + "description": "Unknown" + }, + { + "name": "Char Slot", + "type": "int", + "size": 4, + "description": "Character slot index (0-based)" + }, + { + "name": "Client IP", + "type": "int", + "size": 4, + "description": "Client IP address" + } + ], + "related": [ + { + "id": "0x1B", + "relationship": "response", + "note": "Login confirmation sent on success" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 210 + } + }, + { + "id": "0xA0", + "name": "Play Server", + "description": "Request to connect to a specific game server from the server list.", + "direction": "incoming", + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA0", + "description": "Packet identifier" + }, + { + "name": "Server Index", + "type": "short", + "size": 2, + "description": "Index of selected server in the list" + } + ], + "related": [ + { + "id": "0x8C", + "relationship": "response", + "note": "Server connection details" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 398 + } + }, + { + "id": "0x83", + "name": "Delete Character", + "description": "Request to delete a character from the account.", + "direction": "incoming", + "isDynamic": false, + "size": 39, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x83", + "description": "Packet identifier" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Account password for verification" + }, + { + "name": "Char Index", + "type": "int", + "size": 4, + "description": "Character slot index to delete" + }, + { + "name": "Client IP", + "type": "int", + "size": 4, + "description": "Client IP address" + } + ], + "related": [ + { + "id": "0x85", + "relationship": "response", + "note": "Delete result" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 185 + } + }, + { + "id": "0xEF", + "name": "Login Server Seed", + "description": "Initial connection packet sent before account login. Contains seed and client version information.", + "direction": "incoming", + "isDynamic": false, + "size": 21, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xEF", + "description": "Packet identifier" + }, + { + "name": "Seed", + "type": "int", + "size": 4, + "description": "Random seed for encryption" + }, + { + "name": "Client Major", + "type": "int", + "size": 4, + "description": "Client major version" + }, + { + "name": "Client Minor", + "type": "int", + "size": 4, + "description": "Client minor version" + }, + { + "name": "Client Revision", + "type": "int", + "size": 4, + "description": "Client revision" + }, + { + "name": "Client Patch", + "type": "int", + "size": 4, + "description": "Client patch level" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 419 + } + }, + { + "id": "0xBD", + "name": "Client Version", + "description": "Response to server\u0027s version request (0xBD). Contains the client version string.", + "direction": "incoming", + "isDynamic": true, + "size": "3 + version string length", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBD", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Version", + "type": "ascii", + "description": "Client version string (e.g., \u00277.0.95.0\u0027)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 193 + } + }, + { + "id": "0xE1", + "name": "Client Type", + "description": "Sent by the client to identify the client type and version.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xE1", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Unknown", + "type": "ushort", + "size": 2, + "description": "Unknown" + }, + { + "name": "Client Type", + "type": "ushort", + "size": 2, + "description": "Client type identifier" + }, + { + "name": "Version", + "type": "ascii", + "description": "Client version string" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 200 + } + }, + { + "id": "0x00", + "name": "Create Character (Old)", + "description": "Request to create a new character. This is the older 104-byte version with 3 starting skills. Replaced by 0xF8 in client 7.0.16.0+.", + "direction": "incoming", + "isDynamic": false, + "size": 104, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Packet identifier" + }, + { + "name": "Unknown1", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown3", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name" + }, + { + "name": "Unknown4", + "type": "byte[2]", + "size": 2, + "description": "Unknown" + }, + { + "name": "Flags", + "type": "int", + "size": 4, + "description": "Client flags" + }, + { + "name": "Unknown5", + "type": "byte[8]", + "size": 8, + "description": "Unknown" + }, + { + "name": "Profession", + "type": "byte", + "size": 1, + "description": "Starting profession" + }, + { + "name": "Unknown6", + "type": "byte[15]", + "size": 15, + "description": "Unknown" + }, + { + "name": "Gender Race", + "type": "byte", + "size": 1, + "description": "Gender and race combined value" + }, + { + "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": "Skill1Id", + "type": "byte", + "size": 1, + "description": "First skill ID" + }, + { + "name": "Skill1Value", + "type": "byte", + "size": 1, + "description": "First skill value" + }, + { + "name": "Skill2Id", + "type": "byte", + "size": 1, + "description": "Second skill ID" + }, + { + "name": "Skill2Value", + "type": "byte", + "size": 1, + "description": "Second skill value" + }, + { + "name": "Skill3Id", + "type": "byte", + "size": 1, + "description": "Third skill ID" + }, + { + "name": "Skill3Value", + "type": "byte", + "size": 1, + "description": "Third skill value" + }, + { + "name": "Skin Hue", + "type": "ushort", + "size": 2, + "description": "Skin color hue" + }, + { + "name": "Hair Style", + "type": "short", + "size": 2, + "description": "Hair style ID" + }, + { + "name": "Hair Hue", + "type": "short", + "size": 2, + "description": "Hair color hue" + }, + { + "name": "Facial Hair Style", + "type": "short", + "size": 2, + "description": "Facial hair style ID" + }, + { + "name": "Facial Hair Hue", + "type": "short", + "size": 2, + "description": "Facial hair color hue" + }, + { + "name": "Unknown7", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "City Index", + "type": "byte", + "size": 1, + "description": "Starting city index" + }, + { + "name": "Char Slot", + "type": "int", + "size": 4, + "description": "Character slot" + }, + { + "name": "Client IP", + "type": "int", + "size": 4, + "description": "Client IP" + }, + { + "name": "Shirt Hue", + "type": "short", + "size": 2, + "description": "Starting shirt hue" + }, + { + "name": "Pants Hue", + "type": "short", + "size": 2, + "description": "Starting pants hue" + } + ], + "related": [ + { + "id": "0xF8", + "relationship": "variant", + "note": "Create Character (New) for 7.0.16.0+ with 4th skill" + } + ], + "clientVersion": { + "max": "7.0.15.x", + "notes": "Replaced by 0xF8 in client 7.0.16.0+" + }, + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingAccountPackets.cs", + "line": 58 + } + }, + { + "id": "0xF8", + "name": "Create Character (New)", + "description": "Request to create a new character. This is the newer 106-byte version with support for 4 skills.", + "direction": "incoming", + "isDynamic": false, + "size": 106, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF8", + "description": "Packet identifier" + }, + { + "name": "Unknown1", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown3", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name" + }, + { + "name": "Unknown4", + "type": "byte[2]", + "size": 2, + "description": "Unknown" + }, + { + "name": "Flags", + "type": "int", + "size": 4, + "description": "Client flags" + }, + { + "name": "Unknown5", + "type": "byte[8]", + "size": 8, + "description": "Unknown" + }, + { + "name": "Profession", + "type": "byte", + "size": 1, + "description": "Starting profession" + }, + { + "name": "Unknown6", + "type": "byte[15]", + "size": 15, + "description": "Unknown" + }, + { + "name": "Gender Race", + "type": "byte", + "size": 1, + "description": "Gender and race combined value" + }, + { + "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": "Skill1Id", + "type": "byte", + "size": 1, + "description": "First skill ID" + }, + { + "name": "Skill1Value", + "type": "byte", + "size": 1, + "description": "First skill value" + }, + { + "name": "Skill2Id", + "type": "byte", + "size": 1, + "description": "Second skill ID" + }, + { + "name": "Skill2Value", + "type": "byte", + "size": 1, + "description": "Second skill value" + }, + { + "name": "Skill3Id", + "type": "byte", + "size": 1, + "description": "Third skill ID" + }, + { + "name": "Skill3Value", + "type": "byte", + "size": 1, + "description": "Third skill value" + }, + { + "name": "Skill4Id", + "type": "byte", + "size": 1, + "description": "Fourth skill ID (newer clients)" + }, + { + "name": "Skill4Value", + "type": "byte", + "size": 1, + "description": "Fourth skill value (newer clients)" + }, + { + "name": "Skin Hue", + "type": "ushort", + "size": 2, + "description": "Skin color hue" + }, + { + "name": "Hair Style", + "type": "short", + "size": 2, + "description": "Hair style ID" + }, + { + "name": "Hair Hue", + "type": "short", + "size": 2, + "description": "Hair color hue" + }, + { + "name": "Facial Hair Style", + "type": "short", + "size": 2, + "description": "Facial hair style ID" + }, + { + "name": "Facial Hair Hue", + "type": "short", + "size": 2, + "description": "Facial hair color hue" + }, + { + "name": "Unknown7", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "City Index", + "type": "byte", + "size": 1, + "description": "Starting city index" + }, + { + "name": "Char Slot", + "type": "int", + "size": 4, + "description": "Character slot" + }, + { + "name": "Client IP", + "type": "int", + "size": 4, + "description": "Client IP" + }, + { + "name": "Shirt Hue", + "type": "short", + "size": 2, + "description": "Starting shirt hue" + }, + { + "name": "Pants Hue", + "type": "short", + "size": 2, + "description": "Starting pants hue" + } + ], + "related": [ + { + "id": "0x00", + "relationship": "variant", + "note": "Create Character (Old) for pre-7.0.16.0 with 3 skills" + } + ], + "clientVersion": { + "min": "7.0.16.0", + "notes": "Replaces 0x00, adds 4th starting skill" + }, + "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." + } + ] +} diff --git a/docs/packets/incoming/assistant.json b/docs/packets/incoming/assistant.json new file mode 100644 index 000000000..4af31ea9b --- /dev/null +++ b/docs/packets/incoming/assistant.json @@ -0,0 +1,39 @@ +{ + "category": "Assistant", + "packets": [ + { + "id": "0xBE", + "name": "Assistant Version", + "description": "Client sends assistant version information. Razor CE sends version as ASCII string.", + "direction": "incoming", + "isDynamic": true, + "size": "3+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBE", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Version String", + "type": "ascii", + "size": "var", + "description": "Assistant version string (Razor CE sends \u0027version\u0027 or \u0027ProductName version\u0027)" + } + ], + "notes": "Razor Community Edition sends version as ASCII. Legacy UOAssist would send int32 + ASCII client version.", + "source": { + "file": "Projects/UOContent/Assistants/AssistantHandler.cs", + "line": 69 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/book.json b/docs/packets/incoming/book.json new file mode 100644 index 000000000..f75f7da55 --- /dev/null +++ b/docs/packets/incoming/book.json @@ -0,0 +1,216 @@ +{ + "category": "Book", + "packets": [ + { + "id": "0x66", + "name": "Book Content Change", + "description": "Client sends updated book page content when player edits a writable book.", + "direction": "incoming", + "isDynamic": true, + "size": "9+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x66", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book being edited" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages being updated" + }, + { + "name": "Pages", + "type": "loop", + "description": "Page contents being updated", + "loop": { + "countField": "pageCount", + "fields": [ + { + "name": "Page Index", + "type": "ushort", + "size": 2, + "description": "Page number (1-indexed)" + }, + { + "name": "Line Count", + "type": "ushort", + "size": 2, + "description": "Number of lines on page (max 8)" + }, + { + "name": "Lines", + "type": "loop", + "description": "Lines on the page", + "loop": { + "countField": "lineCount", + "fields": [ + { + "name": "Text", + "type": "utf8-t", + "description": "Line text (max 80 characters)" + } + ] + } + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Items/Books/BookPackets.cs", + "line": 87 + } + }, + { + "id": "0xD4", + "name": "Book Header Change", + "description": "Client sends updated book title and author when player edits a writable book\u0027s cover.", + "direction": "incoming", + "isDynamic": true, + "size": "13+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD4", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book being edited" + }, + { + "name": "Flags", + "type": "ushort", + "size": 2, + "description": "Book flags (ignored by server)" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages (ignored by server)" + }, + { + "name": "Title Length", + "type": "ushort", + "size": 2, + "description": "Length of title string including null terminator (max 61)" + }, + { + "name": "Title", + "type": "utf8-t", + "description": "Book title (max 60 characters)" + }, + { + "name": "Author Length", + "type": "ushort", + "size": 2, + "description": "Length of author string including null terminator (max 31)" + }, + { + "name": "Author", + "type": "utf8-t", + "description": "Book author (max 30 characters)" + } + ], + "related": [ + { + "id": "0x93", + "direction": "incoming", + "relationship": "variant", + "note": "Old Header Change format for older clients" + } + ], + "source": { + "file": "Projects/UOContent/Items/Books/BookPackets.cs", + "line": 51 + } + }, + { + "id": "0x93", + "name": "Old Book Header Change", + "description": "Legacy format for book header changes. Uses fixed-size ASCII strings.", + "direction": "incoming", + "isDynamic": false, + "size": 99, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x93", + "description": "Packet identifier" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book being edited" + }, + { + "name": "Flags", + "type": "ushort", + "size": 2, + "description": "Book flags (ignored by server)" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages (ignored by server)" + }, + { + "name": "Title", + "type": "ascii", + "size": 60, + "description": "Book title (fixed 60 bytes, null-padded)" + }, + { + "name": "Author", + "type": "ascii", + "size": 30, + "description": "Book author (fixed 30 bytes, null-padded)" + } + ], + "related": [ + { + "id": "0xD4", + "direction": "incoming", + "relationship": "variant", + "note": "New Header Change format for newer clients" + } + ], + "notes": "Old format used by older clients. Title and author are fixed-size ASCII.", + "source": { + "file": "Projects/UOContent/Items/Books/BookPackets.cs", + "line": 32 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/bulletinboard.json b/docs/packets/incoming/bulletinboard.json new file mode 100644 index 000000000..9238e5e9c --- /dev/null +++ b/docs/packets/incoming/bulletinboard.json @@ -0,0 +1,250 @@ +{ + "category": "Bulletin Board", + "packets": [ + { + "id": "0x71", + "subId": "0x03", + "name": "Bulletin Board Request Content", + "description": "Client requests the full content of a bulletin board message.", + "direction": "incoming", + "isDynamic": true, + "size": "12", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x03", + "description": "Request Content command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Message Serial", + "type": "uint", + "size": 4, + "description": "Serial of the message to read" + } + ], + "related": [ + { + "id": "0x71", + "subId": "0x02", + "direction": "outgoing", + "relationship": "response", + "note": "Message Content response" + } + ], + "source": { + "file": "Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs", + "line": 78 + } + }, + { + "id": "0x71", + "subId": "0x04", + "name": "Bulletin Board Request Header", + "description": "Client requests the header (poster, subject, time) of a bulletin board message.", + "direction": "incoming", + "isDynamic": true, + "size": "12", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x04", + "description": "Request Header command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Message Serial", + "type": "uint", + "size": 4, + "description": "Serial of the message" + } + ], + "related": [ + { + "id": "0x71", + "subId": "0x01", + "direction": "outgoing", + "relationship": "response", + "note": "Message Header response" + } + ], + "source": { + "file": "Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs", + "line": 88 + } + }, + { + "id": "0x71", + "subId": "0x05", + "name": "Bulletin Board Post Message", + "description": "Client posts a new message or reply to the bulletin board.", + "direction": "incoming", + "isDynamic": true, + "size": "12+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x05", + "description": "Post Message command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Thread Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent message (0 for new thread)" + }, + { + "name": "Subject Length", + "type": "byte", + "size": 1, + "description": "Length of subject string" + }, + { + "name": "Subject", + "type": "utf8", + "description": "Message subject" + }, + { + "name": "Line Count", + "type": "byte", + "size": 1, + "description": "Number of message lines" + }, + { + "name": "Lines", + "type": "loop", + "description": "Message body lines", + "loop": { + "countField": "Line Count", + "fields": [ + { + "name": "Line Length", + "type": "byte", + "size": 1, + "description": "Length of this line" + }, + { + "name": "Line", + "type": "utf8", + "description": "Line text" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs", + "line": 98 + } + }, + { + "id": "0x71", + "subId": "0x06", + "name": "Bulletin Board Remove Message", + "description": "Client requests to delete a bulletin board message.", + "direction": "incoming", + "isDynamic": true, + "size": "12", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x06", + "description": "Remove Message command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Message Serial", + "type": "uint", + "size": 4, + "description": "Serial of the message to delete" + } + ], + "notes": "Only the message poster or GameMaster+ can delete messages.", + "source": { + "file": "Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs", + "line": 153 + } + } + ] +} diff --git a/docs/packets/incoming/chat.json b/docs/packets/incoming/chat.json new file mode 100644 index 000000000..8bbe1a998 --- /dev/null +++ b/docs/packets/incoming/chat.json @@ -0,0 +1,93 @@ +{ + "category": "Chat", + "packets": [ + { + "id": "0xB5", + "name": "Open Chat Window Request", + "description": "Client requests to open the chat window. Newer clients don\u0027t send chat username.", + "direction": "incoming", + "isDynamic": false, + "size": 64, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB5", + "description": "Packet identifier" + }, + { + "name": "Reserved", + "type": "byte[]", + "size": 63, + "description": "Reserved/unused (newer clients don\u0027t send chat username)" + } + ], + "related": [ + { + "id": "0xB2", + "direction": "outgoing", + "relationship": "response", + "note": "Server responds with Chat Message (OpenChatWindow command)" + } + ], + "source": { + "file": "Projects/UOContent/Engines/Chat/ChatPackets.cs", + "line": 30 + } + }, + { + "id": "0xB3", + "name": "Chat Action", + "description": "Client sends chat action commands like sending messages, joining channels, etc.", + "direction": "incoming", + "isDynamic": true, + "size": "8+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB3", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., \u0027enu\u0027 for English)" + }, + { + "name": "Action ID", + "type": "short", + "size": 2, + "description": "Chat action ID" + }, + { + "name": "Parameter", + "type": "utf16be", + "size": "var", + "description": "Action parameter (Big Endian Unicode)" + } + ], + "related": [ + { + "id": "0xB2", + "direction": "outgoing", + "relationship": "response", + "note": "Server responds with Chat Message" + } + ], + "source": { + "file": "Projects/UOContent/Engines/Chat/ChatPackets.cs", + "line": 51 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/encoded.json b/docs/packets/incoming/encoded.json new file mode 100644 index 000000000..551f582e3 --- /dev/null +++ b/docs/packets/incoming/encoded.json @@ -0,0 +1,959 @@ +{ + "category": "Encoded Commands (0xD7)", + "packets": [ + { + "id": "0xD7", + "name": "Encoded Command", + "description": "Wrapper packet for encoded commands (0xD7 subpackets). Used for house design, abilities, guild/quest requests.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Entity Serial", + "type": "uint", + "size": 4, + "description": "Serial of target entity" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "description": "Encoded command ID" + }, + { + "name": "Data", + "type": "byte[]", + "description": "Subcommand-specific data" + } + ], + "subpackets": [ + { + "subId": "0x02", + "name": "Backup", + "description": "Backup current house design state", + "direction": "incoming" + }, + { + "subId": "0x03", + "name": "Restore", + "description": "Restore house design from backup", + "direction": "incoming" + }, + { + "subId": "0x04", + "name": "Commit", + "description": "Commit house design changes", + "direction": "incoming" + }, + { + "subId": "0x05", + "name": "Delete Component", + "description": "Delete component from house", + "direction": "incoming" + }, + { + "subId": "0x06", + "name": "Build Component", + "description": "Place component in house", + "direction": "incoming" + }, + { + "subId": "0x0C", + "name": "Close Tool", + "description": "Close house design tool", + "direction": "incoming" + }, + { + "subId": "0x0D", + "name": "Add Stairs", + "description": "Add stairs to house design", + "direction": "incoming" + }, + { + "subId": "0x0E", + "name": "Sync Request", + "description": "Synchronize house design state", + "direction": "incoming" + }, + { + "subId": "0x10", + "name": "Clear Floor", + "description": "Clear a floor in house design", + "direction": "incoming" + }, + { + "subId": "0x12", + "name": "Change Floor Level", + "description": "Change visible floor level", + "direction": "incoming" + }, + { + "subId": "0x13", + "name": "Add Roof", + "description": "Add roof tile (SE+)", + "direction": "incoming" + }, + { + "subId": "0x14", + "name": "Delete Roof", + "description": "Delete roof tile (SE+)", + "direction": "incoming" + }, + { + "subId": "0x19", + "name": "Set Weapon Ability", + "description": "Select weapon special ability", + "direction": "incoming" + }, + { + "subId": "0x1A", + "name": "Revert", + "description": "Revert house to original state", + "direction": "incoming" + }, + { + "subId": "0x28", + "name": "Guild Gump Request", + "description": "Open guild gump", + "direction": "incoming" + }, + { + "subId": "0x32", + "name": "Quest Gump Request", + "description": "Open quest/MLB gump", + "direction": "incoming" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 457 + } + }, + { + "id": "0xD7/0x02", + "subId": "0x02", + "name": "House Design: Backup", + "description": "Client requests to backup current house design state.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x02", + "description": "Backup subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1024 + } + }, + { + "id": "0xD7/0x03", + "subId": "0x03", + "name": "House Design: Restore", + "description": "Client requests to restore house design from backup.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x03", + "description": "Restore subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1025 + } + }, + { + "id": "0xD7/0x04", + "subId": "0x04", + "name": "House Design: Commit", + "description": "Client commits the current house design changes.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x04", + "description": "Commit subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1026 + } + }, + { + "id": "0xD7/0x05", + "subId": "0x05", + "name": "House Design: Delete Component", + "description": "Client requests to delete a component from house design.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x05", + "description": "Delete subcommand" + }, + { + "name": "Tile ID", + "type": "int", + "size": 4, + "description": "Tile graphic ID to delete" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X offset from foundation" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y offset from foundation" + }, + { + "name": "Z", + "type": "int", + "size": 4, + "description": "Z offset from foundation" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1027 + } + }, + { + "id": "0xD7/0x06", + "subId": "0x06", + "name": "House Design: Build Component", + "description": "Client requests to place a component in house design.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x06", + "description": "Build subcommand" + }, + { + "name": "Tile ID", + "type": "int", + "size": 4, + "description": "Tile graphic ID to place" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X offset from foundation" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y offset from foundation" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1028 + } + }, + { + "id": "0xD7/0x0C", + "subId": "0x0C", + "name": "House Design: Close Tool", + "description": "Client closes the house design tool.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0C", + "description": "Close subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1029 + } + }, + { + "id": "0xD7/0x0D", + "subId": "0x0D", + "name": "House Design: Add Stairs", + "description": "Client requests to add stairs to house design.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0D", + "description": "Stairs subcommand" + }, + { + "name": "Tile ID", + "type": "int", + "size": 4, + "description": "Stair tile graphic ID" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X offset from foundation" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y offset from foundation" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1030 + } + }, + { + "id": "0xD7/0x0E", + "subId": "0x0E", + "name": "House Design: Sync Request", + "description": "Client requests to synchronize house design state.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0E", + "description": "Sync subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1031 + } + }, + { + "id": "0xD7/0x10", + "subId": "0x10", + "name": "House Design: Clear Floor", + "description": "Client requests to clear a floor in house design.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x10", + "description": "Clear subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1032 + } + }, + { + "id": "0xD7/0x12", + "subId": "0x12", + "name": "House Design: Change Floor Level", + "description": "Client changes the visible floor level in house design.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x12", + "description": "Level subcommand" + }, + { + "name": "Floor", + "type": "int", + "size": 4, + "description": "Floor level (1-4)" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1033 + } + }, + { + "id": "0xD7/0x13", + "subId": "0x13", + "name": "House Design: Add Roof", + "description": "Client requests to add a roof tile (Samurai Empire+).", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x13", + "description": "Roof subcommand" + }, + { + "name": "Tile ID", + "type": "int", + "size": 4, + "description": "Roof tile graphic ID" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X offset from foundation" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y offset from foundation" + }, + { + "name": "Z", + "type": "int", + "size": 4, + "description": "Z offset for roof placement" + } + ], + "clientVersion": { + "min": "Samurai Empire", + "notes": "Added with Samurai Empire expansion" + }, + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1035 + } + }, + { + "id": "0xD7/0x14", + "subId": "0x14", + "name": "House Design: Delete Roof", + "description": "Client requests to delete a roof tile (Samurai Empire+).", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x14", + "description": "Roof Delete subcommand" + }, + { + "name": "Tile ID", + "type": "int", + "size": 4, + "description": "Roof tile graphic ID" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X offset from foundation" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y offset from foundation" + }, + { + "name": "Z", + "type": "int", + "size": 4, + "description": "Z offset of roof to delete" + } + ], + "clientVersion": { + "min": "Samurai Empire", + "notes": "Added with Samurai Empire expansion" + }, + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1036 + } + }, + { + "id": "0xD7/0x19", + "subId": "0x19", + "name": "Set Weapon Ability", + "description": "Client selects a weapon special ability.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Combat"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Player serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x19", + "description": "Set Ability subcommand" + }, + { + "name": "Ability Index", + "type": "int", + "size": 4, + "description": "Ability index (0 = clear, 1+ = ability index)" + } + ], + "related": [ + { + "id": "0xBF/0x21", + "relationship": "response", + "note": "Clear Weapon Ability" + }, + { + "id": "0xBF/0x25", + "relationship": "response", + "note": "Toggle Special Ability" + } + ], + "source": { + "file": "Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs", + "line": 11 + } + }, + { + "id": "0xD7/0x1A", + "subId": "0x1A", + "name": "House Design: Revert", + "description": "Client requests to revert house design to original state.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "House foundation serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x1A", + "description": "Revert subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1038 + } + }, + { + "id": "0xD7/0x28", + "subId": "0x28", + "name": "Guild Gump Request", + "description": "Client requests to open the guild gump.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Guild"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Player serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x28", + "description": "Guild Gump subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 54 + } + }, + { + "id": "0xD7/0x32", + "subId": "0x32", + "name": "Quest Gump Request", + "description": "Client requests to open the quest/MLB gump.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Quest"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Player serial" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x32", + "description": "Quest Gump subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 55 + } + } + ] +} diff --git a/docs/packets/incoming/entity.json b/docs/packets/incoming/entity.json new file mode 100644 index 000000000..f5e62ab93 --- /dev/null +++ b/docs/packets/incoming/entity.json @@ -0,0 +1,142 @@ +{ + "category": "Item", + "tags": ["Mobile"], + "packets": [ + { + "id": "0x06", + "name": "Use Request (Double-Click)", + "description": "Sent when the player double-clicks an item or mobile. Can also trigger paperdoll if high bit is set.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x06", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target. If high bit (0x80000000) is set, opens player\u0027s paperdoll instead." + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingEntityPackets.cs", + "line": 61 + } + }, + { + "id": "0x09", + "name": "Look Request (Single-Click)", + "description": "Sent when the player single-clicks an item or mobile to see its name/properties.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x09", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target entity" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingEntityPackets.cs", + "line": 105 + } + }, + { + "id": "0xB6", + "name": "Object Help Request", + "description": "Sent when the player requests help/info about an object (Shift+Click or context menu).", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB6", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target entity" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "Language", + "type": "ascii", + "size": 3, + "description": "Language code (e.g., \u0027ENU\u0027)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingEntityPackets.cs", + "line": 32 + } + }, + { + "id": "0xD6", + "name": "Batch Query Properties", + "description": "Sent by the client to request Object Property Lists (tooltips) for multiple entities at once.", + "direction": "incoming", + "isDynamic": true, + "size": "3 + (4 x entityCount)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD6", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serials", + "type": "array", + "description": "List of entity serials to query", + "loop": { + "countField": "(length-3)/4", + "fields": [ + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingEntityPackets.cs", + "line": 154 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/extended.json b/docs/packets/incoming/extended.json new file mode 100644 index 000000000..a302395d8 --- /dev/null +++ b/docs/packets/incoming/extended.json @@ -0,0 +1,1264 @@ +{ + "category": "Extended Commands (0xBF)", + "packets": [ + { + "id": "0xBF", + "name": "Extended Command", + "description": "Wrapper packet for extended command subpackets. Used for both client-to-server and server-to-client communication.", + "direction": "both", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "description": "Extended command ID" + }, + { + "name": "Data", + "type": "byte[]", + "description": "Subcommand-specific data" + } + ], + "subpackets": [ + { + "subId": "0x04", + "name": "Close Gump", + "description": "Close a generic gump", + "direction": "outgoing" + }, + { + "subId": "0x05", + "name": "Screen Size", + "description": "Client reports screen dimensions", + "direction": "incoming" + }, + { + "subId": "0x06", + "name": "Party Message", + "description": "Party system commands and messages", + "direction": "both" + }, + { + "subId": "0x07", + "name": "Quest Arrow Click", + "description": "Client clicked the quest tracking arrow", + "direction": "incoming" + }, + { + "subId": "0x08", + "name": "Map Change", + "description": "Notify client of map/facet change", + "direction": "outgoing" + }, + { + "subId": "0x09", + "name": "Disarm Request", + "description": "Request to disarm opponent", + "direction": "incoming" + }, + { + "subId": "0x0A", + "name": "Stun Request", + "description": "Request to stun opponent", + "direction": "incoming" + }, + { + "subId": "0x0B", + "name": "Language", + "description": "Client language setting", + "direction": "incoming" + }, + { + "subId": "0x0C", + "name": "Status Bar Close", + "description": "Client closed a status bar", + "direction": "incoming" + }, + { + "subId": "0x0E", + "name": "Animate", + "description": "Request to play animation", + "direction": "incoming" + }, + { + "subId": "0x0F", + "name": "Client Info", + "description": "Client type and flags (Spy on Client)", + "direction": "incoming" + }, + { + "subId": "0x10", + "name": "Query Object Properties", + "description": "Request object property list", + "direction": "incoming" + }, + { + "subId": "0x13", + "name": "Context Menu Request", + "description": "Request context menu for entity", + "direction": "incoming" + }, + { + "subId": "0x14", + "name": "Context Menu Display", + "description": "Display context menu to client", + "direction": "outgoing" + }, + { + "subId": "0x15", + "name": "Context Menu Response", + "description": "Selected context menu option", + "direction": "incoming" + }, + { + "subId": "0x18", + "name": "Map Patches", + "description": "Send map diff/patch information", + "direction": "outgoing" + }, + { + "subId": "0x19", + "name": "Stat Lock Info", + "description": "Stat lock states and bonded status", + "direction": "outgoing" + }, + { + "subId": "0x1A", + "name": "Stat Lock Change", + "description": "Change STR/DEX/INT lock state", + "direction": "incoming" + }, + { + "subId": "0x1B", + "name": "New Spellbook Content", + "description": "Spellbook spell list (AOS+)", + "direction": "outgoing" + }, + { + "subId": "0x1C", + "name": "Cast Spell", + "description": "Cast spell by ID", + "direction": "incoming" + }, + { + "subId": "0x1E", + "name": "Query Design Details", + "description": "Request house design details", + "direction": "incoming" + }, + { + "subId": "0x21", + "name": "Set Weapon Ability", + "description": "Clear weapon ability selection", + "direction": "outgoing" + }, + { + "subId": "0x22", + "name": "Damage", + "description": "Display damage number (old clients)", + "direction": "outgoing" + }, + { + "subId": "0x25", + "name": "Toggle Special Ability", + "description": "Toggle weapon special move icon", + "direction": "outgoing" + }, + { + "subId": "0x26", + "name": "Speed Mode", + "description": "Set movement speed mode", + "direction": "outgoing" + }, + { + "subId": "0x2A", + "name": "Race Change Reply", + "description": "Response to race change confirmation", + "direction": "incoming" + }, + { + "subId": "0x2C", + "name": "Bandage Target", + "description": "Apply bandage to target", + "direction": "incoming" + }, + { + "subId": "0x2D", + "name": "Targeted Spell", + "description": "Cast spell with pre-selected target", + "direction": "incoming" + }, + { + "subId": "0x2E", + "name": "Targeted Skill Use", + "description": "Use skill with pre-selected target", + "direction": "incoming" + }, + { + "subId": "0x30", + "name": "Target By Resource Macro", + "description": "Resource-based targeting macro", + "direction": "incoming" + }, + { + "subId": "0x32", + "name": "Toggle Flying", + "description": "Toggle gargoyle flying mode", + "direction": "incoming" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 43 + } + }, + { + "id": "0xBF/0x05", + "subId": "0x05", + "name": "Screen Size", + "description": "Client reports screen size.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x05", + "description": "Screen Size subcommand" + }, + { + "name": "Width", + "type": "int", + "size": 4, + "description": "Screen width" + }, + { + "name": "Unknown", + "type": "int", + "size": 4, + "description": "Unknown value" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 136 + } + }, + { + "id": "0xBF/0x06", + "subId": "0x06", + "name": "Party Message", + "description": "Client sends party-related commands.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x06", + "description": "Party Message subcommand" + }, + { + "name": "Party Command", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Party command type", + "values": [ + { + "value": 1, + "name": "Add Member", + "description": "Add member to party" + }, + { + "value": 2, + "name": "Remove Member", + "description": "Remove member from party" + }, + { + "value": 3, + "name": "Private Message", + "description": "Send private message to party member" + }, + { + "value": 4, + "name": "Public Message", + "description": "Send public message to party" + }, + { + "value": 6, + "name": "Set Can Loot", + "description": "Set loot permission" + }, + { + "value": 8, + "name": "Accept", + "description": "Accept party invitation" + }, + { + "value": 9, + "name": "Decline", + "description": "Decline party invitation" + } + ] + }, + { + "name": "Data", + "type": "byte[]", + "description": "Command-specific data (target serial, message text)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 142 + } + }, + { + "id": "0xBF/0x07", + "subId": "0x07", + "name": "Quest Arrow Click", + "description": "Client clicked the quest tracking arrow.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x07", + "description": "Quest Arrow Click subcommand" + }, + { + "name": "Right Click", + "type": "bool", + "size": 1, + "description": "True if right-clicked, false if left-clicked" + } + ], + "related": [ + { + "id": "0xBA", + "relationship": "response", + "note": "Quest Arrow packet" + } + ], + "source": { + "file": "Projects/UOContent/Skills/Tracking/Tracking.cs", + "line": 26 + } + }, + { + "id": "0xBF/0x09", + "subId": "0x09", + "name": "Disarm Request", + "description": "Client requests to disarm opponent.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x09", + "description": "Disarm Request subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 289 + } + }, + { + "id": "0xBF/0x0A", + "subId": "0x0A", + "name": "Stun Request", + "description": "Client requests to stun opponent.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0A", + "description": "Stun Request subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 277 + } + }, + { + "id": "0xBF/0x0B", + "subId": "0x0B", + "name": "Language", + "description": "Client sets language preference.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0B", + "description": "Language subcommand" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., \u0027ENU\u0027)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 343 + } + }, + { + "id": "0xBF/0x0C", + "subId": "0x0C", + "name": "Close Status", + "description": "Client closes a status gump.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0C", + "description": "Close Status subcommand" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile whose status to close" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 338 + } + }, + { + "id": "0xBF/0x0E", + "subId": "0x0E", + "name": "Animate", + "description": "Client requests to play an animation.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0E", + "description": "Animate subcommand" + }, + { + "name": "Action", + "type": "int", + "size": 4, + "description": "Animation action ID (must be in valid list)" + } + ], + "notes": "Only specific animation IDs are allowed for security.", + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 233 + } + }, + { + "id": "0xBF/0x0F", + "subId": "0x0F", + "name": "Client Info", + "description": "Client type information (Spy on Client). No data is read from this packet.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0F", + "description": "Client Info subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 52 + } + }, + { + "id": "0xBF/0x10", + "subId": "0x10", + "name": "Query Properties", + "description": "Client queries Object Property List (tooltip) for an entity.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x10", + "description": "Query Properties subcommand" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity to query" + } + ], + "related": [ + { + "id": "0xDC", + "direction": "outgoing", + "relationship": "response", + "note": "OPL Info packet" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 355 + } + }, + { + "id": "0xBF/0x13", + "subId": "0x13", + "name": "Context Menu Request", + "description": "Client requests context menu for an entity.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x13", + "description": "Context Menu Request subcommand" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity to show context menu for" + } + ], + "related": [ + { + "id": "0xBF/0x14", + "relationship": "response", + "note": "Context Menu Display packet" + } + ], + "source": { + "file": "Projects/UOContent/Context Menus/ContextMenuSystem.cs", + "line": 101 + } + }, + { + "id": "0xBF/0x15", + "subId": "0x15", + "name": "Context Menu Response", + "description": "Client selects an option from context menu.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x15", + "description": "Context Menu Response subcommand" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity context menu was shown for" + }, + { + "name": "Index", + "type": "ushort", + "size": 2, + "description": "Index of selected menu option" + } + ], + "related": [ + { + "id": "0xBF/0x13", + "relationship": "request", + "note": "Context Menu Request packet" + } + ], + "source": { + "file": "Projects/UOContent/Context Menus/ContextMenuSystem.cs", + "line": 48 + } + }, + { + "id": "0xBF/0x1A", + "subId": "0x1A", + "name": "Stat Lock Change", + "description": "Client changes stat lock (STR/DEX/INT).", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x1A", + "description": "Stat Lock Change subcommand" + }, + { + "name": "Stat", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Which stat to change", + "values": [ + { + "value": 0, + "name": "Strength", + "description": "Strength lock" + }, + { + "value": 1, + "name": "Dexterity", + "description": "Dexterity lock" + }, + { + "value": 2, + "name": "Intelligence", + "description": "Intelligence lock" + } + ] + }, + { + "name": "Lock Value", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "New lock state", + "values": [ + { + "value": 0, + "name": "Up", + "description": "Stat gains enabled" + }, + { + "value": 1, + "name": "Down", + "description": "Stat decreases enabled" + }, + { + "value": 2, + "name": "Locked", + "description": "Stat locked" + } + ] + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 301 + } + }, + { + "id": "0xBF/0x1C", + "subId": "0x1C", + "name": "Cast Spell", + "description": "Client casts a spell (optionally from spellbook).", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Spell"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x1C", + "description": "Cast Spell subcommand" + }, + { + "name": "Has Book", + "type": "short", + "size": 2, + "description": "1 if casting from book, 0 otherwise" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of spellbook (if hasBook)", + "condition": "hasBook == 1" + }, + { + "name": "Spell ID", + "type": "short", + "size": 2, + "description": "Spell ID + 1 (1-based)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 257 + } + }, + { + "id": "0xBF/0x1E", + "subId": "0x1E", + "name": "Query Design Details", + "description": "Client requests house design details.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x1E", + "description": "Query Design Details subcommand" + }, + { + "name": "House Serial", + "type": "uint", + "size": 4, + "description": "Serial of house foundation" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HouseFoundation.cs", + "line": 1826 + } + }, + { + "id": "0xBF/0x2A", + "subId": "0x2A", + "name": "Race Change Reply", + "description": "Client response to race change confirmation gump.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x2A", + "description": "Race Change Reply subcommand" + }, + { + "name": "Skin Hue", + "type": "ushort", + "size": 2, + "description": "Selected skin hue", + "condition": "length \u003e 5" + }, + { + "name": "Hair Item ID", + "type": "ushort", + "size": 2, + "description": "Selected hair style", + "condition": "length \u003e 5" + }, + { + "name": "Hair Hue", + "type": "ushort", + "size": 2, + "description": "Selected hair hue", + "condition": "length \u003e 5" + }, + { + "name": "Facial Hair Item ID", + "type": "ushort", + "size": 2, + "description": "Selected facial hair style", + "condition": "length \u003e 5" + }, + { + "name": "Facial Hair Hue", + "type": "ushort", + "size": 2, + "description": "Selected facial hair hue", + "condition": "length \u003e 5" + } + ], + "source": { + "file": "Projects/UOContent/Engines/ML Quests/Gumps/RaceChangeGump.cs", + "line": 199 + } + }, + { + "id": "0xBF/0x2C", + "subId": "0x2C", + "name": "Bandage Target", + "description": "Client uses bandage on a target.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x2C", + "description": "Bandage Target subcommand" + }, + { + "name": "Bandage Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bandage item" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of target mobile" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 387 + } + }, + { + "id": "0xBF/0x2D", + "subId": "0x2D", + "name": "Targeted Spell", + "description": "Client casts spell with pre-selected target.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Spell"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x2D", + "description": "Targeted Spell subcommand" + }, + { + "name": "Spell ID", + "type": "short", + "size": 2, + "description": "Spell ID + 1 (1-based)" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of target entity" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 422 + } + }, + { + "id": "0xBF/0x2E", + "subId": "0x2E", + "name": "Targeted Skill Use", + "description": "Client uses skill with pre-selected target.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x2E", + "description": "Targeted Skill Use subcommand" + }, + { + "name": "Skill ID", + "type": "short", + "size": 2, + "description": "Skill ID" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of target entity" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 429 + } + }, + { + "id": "0xBF/0x30", + "subId": "0x30", + "name": "Target By Resource Macro", + "description": "Client uses resource-based targeting macro.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x30", + "description": "Target By Resource Macro subcommand" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of item" + }, + { + "name": "Resource Type", + "type": "short", + "size": 2, + "description": "Resource type ID" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 439 + } + }, + { + "id": "0xBF/0x32", + "subId": "0x32", + "name": "Toggle Flying", + "description": "Client toggles gargoyle flying mode.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x32", + "description": "Toggle Flying subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 272 + } + } + ] +} diff --git a/docs/packets/incoming/items.json b/docs/packets/incoming/items.json new file mode 100644 index 000000000..da8962d88 --- /dev/null +++ b/docs/packets/incoming/items.json @@ -0,0 +1,292 @@ +{ + "category": "Items", + "packets": [ + { + "id": "0x07", + "name": "Lift Request", + "description": "Client requests to pick up an item from the world or a container.", + "direction": "incoming", + "isDynamic": false, + "size": 7, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x07", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item to lift" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Amount to pick up" + } + ], + "related": [ + { + "id": "0x27", + "relationship": "rej", + "note": "Sent if lift is rejected" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs", + "line": 35 + } + }, + { + "id": "0x08", + "name": "Drop Request", + "description": "Client requests to drop an item at a location or into a container. Size varies by client version.", + "direction": "incoming", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "pre-6017", + "name": "Classic", + "size": 14, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x08", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of item being dropped (ignored)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Target Z coordinate" + }, + { + "name": "Dest", + "type": "uint", + "size": 4, + "description": "Target container/mobile serial, or 0xFFFFFFFF for world" + } + ] + }, + { + "version": "6017+", + "name": "Container Grid Lines", + "condition": "Client version \u003e= 6.0.1.7 (ContainerGridLines)", + "size": 15, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x08", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of item being dropped (ignored)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Target Z coordinate" + }, + { + "name": "Grid Location", + "type": "byte", + "size": 1, + "description": "Grid slot position in container" + }, + { + "name": "Dest", + "type": "uint", + "size": 4, + "description": "Target container/mobile serial, or 0xFFFFFFFF for world" + } + ] + } + ], + "clientVersion": { + "feature": "ContainerGridLines adds gridLocation byte" + }, + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs", + "line": 69 + } + }, + { + "id": "0x13", + "name": "Equip Request", + "description": "Client requests to equip a held item on a mobile.", + "direction": "incoming", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x13", + "description": "Packet identifier" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of item to equip" + }, + { + "name": "Layer", + "type": "byte", + "size": 1, + "description": "Equipment layer" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of target mobile" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs", + "line": 44 + } + }, + { + "id": "0xEC", + "name": "Equip Macro", + "description": "Client requests to equip multiple items from a saved macro.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xEC", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Count", + "type": "byte", + "size": 1, + "description": "Number of items to equip" + }, + { + "name": "Items", + "type": "loop", + "loop": { + "countField": "count", + "fields": [ + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of item to equip" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs", + "line": 112 + } + }, + { + "id": "0xED", + "name": "Unequip Macro", + "description": "Client requests to unequip items from specific layers via macro.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xED", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Count", + "type": "byte", + "size": 1, + "description": "Number of layers to unequip" + }, + { + "name": "Layers", + "type": "loop", + "loop": { + "countField": "count", + "fields": [ + { + "name": "Layer", + "type": "ushort", + "size": 2, + "description": "Layer to unequip from" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingItemPackets.cs", + "line": 125 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/mahjong.json b/docs/packets/incoming/mahjong.json new file mode 100644 index 000000000..7703ed530 --- /dev/null +++ b/docs/packets/incoming/mahjong.json @@ -0,0 +1,907 @@ +{ + "category": "Mahjong", + "packets": [ + { + "id": "0xDA", + "name": "Mahjong Game", + "description": "Mahjong game packets for controlling the in-game Mahjong table. Used for both client commands and server updates.", + "direction": "both", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "description": "Command ID (incoming uses byte prefix + byte command)" + }, + { + "name": "Data", + "type": "byte[]", + "description": "Command-specific data" + } + ], + "subpackets": [ + { + "subId": "0x02", + "name": "Players Info", + "description": "Sends player information for all seats", + "direction": "outgoing" + }, + { + "subId": "0x03", + "name": "Tile Info", + "description": "Sends information about a single tile", + "direction": "outgoing" + }, + { + "subId": "0x04", + "name": "Tiles Info", + "description": "Sends information about all tiles", + "direction": "outgoing" + }, + { + "subId": "0x05", + "name": "General Info", + "description": "Sends game state (dice, dealer, wall break)", + "direction": "outgoing" + }, + { + "subId": "0x06", + "name": "Exit Game", + "description": "Client exits the game", + "direction": "incoming" + }, + { + "subId": "0x0A", + "name": "Give Points", + "description": "Transfer points to another player", + "direction": "incoming" + }, + { + "subId": "0x0B", + "name": "Roll Dice", + "description": "Client requests to roll dice", + "direction": "incoming" + }, + { + "subId": "0x0C", + "name": "Build Walls", + "description": "Dealer builds/resets tile walls", + "direction": "incoming" + }, + { + "subId": "0x0D", + "name": "Reset Scores", + "description": "Dealer resets all scores", + "direction": "incoming" + }, + { + "subId": "0x0F", + "name": "Assign Dealer", + "description": "Assign a new dealer", + "direction": "incoming" + }, + { + "subId": "0x10", + "name": "Open Seat", + "description": "Open a seat for new players", + "direction": "incoming" + }, + { + "subId": "0x11", + "name": "Change Option", + "description": "Change game options", + "direction": "incoming" + }, + { + "subId": "0x15", + "name": "Move Wall Break", + "description": "Move wall break indicator", + "direction": "incoming" + }, + { + "subId": "0x16", + "name": "Toggle Public Hand", + "description": "Toggle hand visibility", + "direction": "incoming" + }, + { + "subId": "0x17", + "name": "Move Tile", + "description": "Move a tile on the board", + "direction": "incoming" + }, + { + "subId": "0x18", + "name": "Move Dealer Indicator", + "description": "Move dealer indicator", + "direction": "incoming" + }, + { + "subId": "0x19", + "name": "Join Game", + "description": "Server opens game interface", + "direction": "outgoing" + }, + { + "subId": "0x1A", + "name": "Relieve", + "description": "Server closes game interface", + "direction": "outgoing" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 46 + } + }, + { + "id": "0xDA", + "subId": "0x06", + "name": "Mahjong Exit Game", + "description": "Client requests to exit the Mahjong game.", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x06", + "description": "Exit Game command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 108 + } + }, + { + "id": "0xDA", + "subId": "0x0A", + "name": "Mahjong Give Points", + "description": "Client transfers points to another player.", + "direction": "incoming", + "isDynamic": false, + "size": 14, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x0A", + "description": "Give Points command" + }, + { + "name": "To Position", + "type": "byte", + "size": 1, + "description": "Target player seat position" + }, + { + "name": "Amount", + "type": "int", + "size": 4, + "description": "Points to transfer" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 120 + } + }, + { + "id": "0xDA", + "subId": "0x0B", + "name": "Mahjong Roll Dice", + "description": "Client requests to roll the dice.", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x0B", + "description": "Roll Dice command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 133 + } + }, + { + "id": "0xDA", + "subId": "0x0C", + "name": "Mahjong Build Walls", + "description": "Dealer requests to reset and build the tile walls.", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x0C", + "description": "Build Walls command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 143 + } + }, + { + "id": "0xDA", + "subId": "0x0D", + "name": "Mahjong Reset Scores", + "description": "Dealer requests to reset all player scores to base value.", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x0D", + "description": "Reset Scores command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 153 + } + }, + { + "id": "0xDA", + "subId": "0x0F", + "name": "Mahjong Assign Dealer", + "description": "Dealer assigns another player as the new dealer.", + "direction": "incoming", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x0F", + "description": "Assign Dealer command" + }, + { + "name": "Position", + "type": "byte", + "size": 1, + "description": "Seat position of new dealer" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 163 + } + }, + { + "id": "0xDA", + "subId": "0x10", + "name": "Mahjong Open Seat", + "description": "Dealer opens a seat, removing the current player.", + "direction": "incoming", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x10", + "description": "Open Seat command" + }, + { + "name": "Position", + "type": "byte", + "size": 1, + "description": "Seat position to open" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 175 + } + }, + { + "id": "0xDA", + "subId": "0x11", + "name": "Mahjong Change Option", + "description": "Dealer changes game options (show scores, spectator vision).", + "direction": "incoming", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Change Option command" + }, + { + "name": "Reserved", + "type": "short", + "size": 2, + "description": "Reserved (not used)" + }, + { + "name": "Reserved 2", + "type": "byte", + "size": 1, + "description": "Reserved (not used)" + }, + { + "name": "Options", + "type": "bitflags", + "size": 1, + "description": "Game options", + "values": [ + { "value": "0x01", "name": "Show Scores", "description": "Display player scores" }, + { "value": "0x02", "name": "Spectator Vision", "description": "Spectators can see all tiles" } + ] + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 192 + } + }, + { + "id": "0xDA", + "subId": "0x15", + "name": "Mahjong Move Wall Break Indicator", + "description": "Dealer moves the wall break indicator position.", + "direction": "incoming", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x15", + "description": "Move Wall Break Indicator command" + }, + { + "name": "Y Position", + "type": "short", + "size": 2, + "description": "New Y coordinate" + }, + { + "name": "X Position", + "type": "short", + "size": 2, + "description": "New X coordinate" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 208 + } + }, + { + "id": "0xDA", + "subId": "0x16", + "name": "Mahjong Toggle Public Hand", + "description": "Player toggles whether their hand is visible to others.", + "direction": "incoming", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x16", + "description": "Toggle Public Hand command" + }, + { + "name": "Reserved", + "type": "short", + "size": 2, + "description": "Reserved (not used)" + }, + { + "name": "Reserved 2", + "type": "byte", + "size": 1, + "description": "Reserved (not used)" + }, + { + "name": "Public Hand", + "type": "bool", + "size": 1, + "description": "True to show hand publicly" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 221 + } + }, + { + "id": "0xDA", + "subId": "0x17", + "name": "Mahjong Move Tile", + "description": "Player moves a tile to a new position with direction and flip state.", + "direction": "incoming", + "isDynamic": false, + "size": 22, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x17", + "description": "Move Tile command" + }, + { + "name": "Tile Number", + "type": "byte", + "size": 1, + "description": "Tile index number" + }, + { + "name": "Current Direction", + "type": "byte", + "size": 1, + "description": "Current tile direction (unused)" + }, + { + "name": "New Direction", + "type": "enum", + "size": 1, + "description": "New tile direction", + "values": [ + { "value": "0", "name": "Up", "description": "Facing up" }, + { "value": "1", "name": "Left", "description": "Facing left" }, + { "value": "2", "name": "Down", "description": "Facing down" }, + { "value": "3", "name": "Right", "description": "Facing right" } + ] + }, + { + "name": "Reserved", + "type": "byte", + "size": 1, + "description": "Reserved byte" + }, + { + "name": "Flip", + "type": "bool", + "size": 1, + "description": "True to flip tile face-up" + }, + { + "name": "Current Y", + "type": "short", + "size": 2, + "description": "Current Y position (unused)" + }, + { + "name": "Current X", + "type": "short", + "size": 2, + "description": "Current X position (unused)" + }, + { + "name": "Reserved 2", + "type": "byte", + "size": 1, + "description": "Reserved byte" + }, + { + "name": "New Y", + "type": "short", + "size": 2, + "description": "New Y position" + }, + { + "name": "New X", + "type": "short", + "size": 2, + "description": "New X position" + }, + { + "name": "Reserved 3", + "type": "byte", + "size": 1, + "description": "Reserved byte" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 236 + } + }, + { + "id": "0xDA", + "subId": "0x18", + "name": "Mahjong Move Dealer Indicator", + "description": "Dealer moves the dealer indicator with direction and wind.", + "direction": "incoming", + "isDynamic": false, + "size": 15, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown byte" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x18", + "description": "Move Dealer Indicator command" + }, + { + "name": "Direction", + "type": "enum", + "size": 1, + "description": "Indicator direction", + "values": [ + { "value": "0", "name": "Up", "description": "Facing up" }, + { "value": "1", "name": "Left", "description": "Facing left" }, + { "value": "2", "name": "Down", "description": "Facing down" }, + { "value": "3", "name": "Right", "description": "Facing right" } + ] + }, + { + "name": "Wind", + "type": "enum", + "size": 1, + "description": "Wind direction displayed", + "values": [ + { "value": "0", "name": "North", "description": "North wind" }, + { "value": "1", "name": "East", "description": "East wind" }, + { "value": "2", "name": "South", "description": "South wind" }, + { "value": "3", "name": "West", "description": "West wind" } + ] + }, + { + "name": "Y Position", + "type": "short", + "size": 2, + "description": "New Y position" + }, + { + "name": "X Position", + "type": "short", + "size": 2, + "description": "New X position" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 271 + } + } + ] +} diff --git a/docs/packets/incoming/map.json b/docs/packets/incoming/map.json new file mode 100644 index 000000000..8f436c546 --- /dev/null +++ b/docs/packets/incoming/map.json @@ -0,0 +1,84 @@ +{ + "category": "Map", + "packets": [ + { + "id": "0x56", + "name": "Map Command", + "description": "Client sends map pin commands for editable map items. Commands include adding, inserting, changing, and removing pins.", + "direction": "incoming", + "isDynamic": false, + "size": 11, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x56", + "description": "Packet identifier" + }, + { + "name": "Map Serial", + "type": "uint", + "size": 4, + "description": "Serial of the map item" + }, + { + "name": "Command", + "type": "enum", + "size": 1, + "description": "Map pin command type", + "values": [ + { "value": "1", "name": "AddPin", "description": "Add a new pin" }, + { "value": "2", "name": "InsertPin", "description": "Insert pin at position" }, + { "value": "3", "name": "ChangePin", "description": "Change existing pin" }, + { "value": "4", "name": "RemovePin", "description": "Remove a pin" }, + { "value": "5", "name": "ClearPins", "description": "Clear all pins" }, + { "value": "6", "name": "ToggleEditable", "description": "Toggle edit mode" } + ] + }, + { + "name": "Number", + "type": "byte", + "size": 1, + "description": "Pin number (for insert, change, remove commands)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate of pin" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate of pin" + } + ], + "related": [ + { + "id": "0x56", + "direction": "outgoing", + "relationship": "related", + "note": "Server map pin commands" + }, + { + "id": "0x90", + "direction": "outgoing", + "relationship": "related", + "note": "Map Details packet (old)" + }, + { + "id": "0xF5", + "direction": "outgoing", + "relationship": "related", + "note": "Map Details packet (new)" + } + ], + "source": { + "file": "Projects/UOContent/Items/Maps/MapItemPackets.cs", + "line": 28 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/message.json b/docs/packets/incoming/message.json new file mode 100644 index 000000000..8014f3c0b --- /dev/null +++ b/docs/packets/incoming/message.json @@ -0,0 +1,300 @@ +{ + "category": "Message", + "packets": [ + { + "id": "0x03", + "name": "ASCII Speech", + "description": "Client sends ASCII-encoded speech message.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x03", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Message type", + "values": [ + { + "value": 0, + "name": "Regular", + "description": "Normal speech" + }, + { + "value": 1, + "name": "System", + "description": "System message" + }, + { + "value": 2, + "name": "Emote", + "description": "Emote (*action*)" + }, + { + "value": 6, + "name": "Label", + "description": "Object label" + }, + { + "value": 7, + "name": "Focus", + "description": "Focused message" + }, + { + "value": 8, + "name": "Whisper", + "description": "Whisper" + }, + { + "value": 9, + "name": "Yell", + "description": "Yell" + }, + { + "value": 10, + "name": "Spell", + "description": "Spell words" + }, + { + "value": 13, + "name": "Guild", + "description": "Guild chat" + }, + { + "value": 14, + "name": "Alliance", + "description": "Alliance chat" + }, + { + "value": 15, + "name": "Command", + "description": "Command" + } + ] + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Text", + "type": "ascii-t", + "description": "Speech text (max 128 chars)" + } + ], + "related": [ + { + "id": "0x1C", + "relationship": "response", + "note": "ASCII Message sent to other clients" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMessagePackets.cs", + "line": 31 + } + }, + { + "id": "0xAD", + "name": "Unicode Speech", + "description": "Client sends Unicode-encoded speech message. Type byte upper bits (0xC0) indicate if keywords are encoded.", + "direction": "incoming", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Standard Unicode", + "condition": "type & 0xC0 == 0", + "size": "12+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xAD", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Type", + "type": "enum", + "size": 1, + "description": "Message type (0xC0 bits clear)", + "values": [ + { + "value": 0, + "name": "Regular", + "description": "Normal speech" + }, + { + "value": 1, + "name": "System", + "description": "System message" + }, + { + "value": 2, + "name": "Emote", + "description": "Emote (*action*)" + }, + { + "value": 8, + "name": "Whisper", + "description": "Whisper" + }, + { + "value": 9, + "name": "Yell", + "description": "Yell" + }, + { + "value": 13, + "name": "Guild", + "description": "Guild chat" + }, + { + "value": 14, + "name": "Alliance", + "description": "Alliance chat" + }, + { + "value": 15, + "name": "Command", + "description": "Command" + } + ] + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., 'ENU')" + }, + { + "name": "Text", + "type": "utf16be-t", + "description": "Speech text (Big Endian Unicode, null-terminated)" + } + ] + }, + { + "name": "Encoded Keywords", + "condition": "type & 0xC0 != 0", + "size": "14+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xAD", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Message type with 0xC0 flag set. Lower 4 bits = message type (see Standard variant)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., 'ENU')" + }, + { + "name": "Keyword Header", + "type": "ushort", + "size": 2, + "description": "Bits 15-4: keyword count (0-50), Bits 3-0: first hold value for packed IDs" + }, + { + "name": "Packed Keywords", + "type": "byte[]", + "description": "12-bit keyword IDs packed alternating: even indices use hold<<8|byte, odd indices use (short&0xFFF0)>>4 with new hold" + }, + { + "name": "Text", + "type": "utf8-t", + "description": "Speech text (UTF-8, null-terminated)" + } + ] + } + ], + "notes": "Encoded keywords use 12-bit speech IDs packed efficiently. Keyword count must be 0-50. The packing alternates: even-indexed keywords combine the previous 4-bit hold with a new byte (12 bits total), odd-indexed keywords read a short and extract bits 15-4 as the ID, bits 3-0 as the next hold.", + "related": [ + { + "id": "0x03", + "direction": "incoming", + "relationship": "variant", + "note": "ASCII Speech (simpler format)" + }, + { + "id": "0xAE", + "direction": "outgoing", + "relationship": "response", + "note": "Unicode Message sent to other clients" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMessagePackets.cs", + "line": 58 + } + } + ] +} diff --git a/docs/packets/incoming/mobile.json b/docs/packets/incoming/mobile.json new file mode 100644 index 000000000..c1860be0a --- /dev/null +++ b/docs/packets/incoming/mobile.json @@ -0,0 +1,168 @@ +{ + "category": "Mobile", + "packets": [ + { + "id": "0x75", + "name": "Rename Request", + "description": "Client requests to rename a mobile (pet).", + "direction": "incoming", + "isDynamic": false, + "size": 35, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x75", + "description": "Packet identifier" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile to rename" + }, + { + "name": "New Name", + "type": "ascii", + "size": 30, + "description": "New name for the mobile" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 32 + } + }, + { + "id": "0x98", + "name": "Mobile Name Request", + "description": "Client requests the name of a mobile.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x98", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile to query" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 43 + } + }, + { + "id": "0xB8", + "name": "Profile Request", + "description": "Client requests to view or edit a mobile's profile.", + "direction": "incoming", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Display Profile", + "condition": "mode == Display (0)", + "size": 8, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB8", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Mode", + "type": "byte", + "size": 1, + "value": "0", + "description": "Display mode" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of target mobile" + } + ] + }, + { + "name": "Edit Profile", + "condition": "mode == Edit (1)", + "size": "12+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB8", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Mode", + "type": "byte", + "size": 1, + "value": "1", + "description": "Edit mode" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of target mobile" + }, + { + "name": "Padding", + "type": "short", + "size": 2, + "description": "Unused padding" + }, + { + "name": "Text Length", + "type": "ushort", + "size": 2, + "description": "Length of text in characters" + }, + { + "name": "Text", + "type": "utf16be", + "description": "New profile text (Big Endian Unicode)" + } + ] + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 53 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/movement.json b/docs/packets/incoming/movement.json new file mode 100644 index 000000000..1898a7675 --- /dev/null +++ b/docs/packets/incoming/movement.json @@ -0,0 +1,56 @@ +{ + "category": "Movement", + "packets": [ + { + "id": "0x02", + "name": "Movement Request", + "description": "Sent by the client when the player attempts to move in a direction. The server responds with either MovementAck (0x22) if successful or MovementRej (0x21) if blocked.", + "direction": "incoming", + "isDynamic": false, + "size": 7, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x02", + "description": "Packet identifier" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Movement direction (0-7). Bit 0x80 indicates running." + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Movement sequence number (1-255, wraps). Used for ack/rej matching." + }, + { + "name": "Fastwalk Key", + "type": "uint", + "size": 4, + "description": "Anti-speedhack prevention key. Set to 0 if fastwalk prevention is disabled." + } + ], + "related": [ + { + "id": "0x21", + "relationship": "rej", + "note": "Sent if movement is blocked" + }, + { + "id": "0x22", + "relationship": "ack", + "note": "Sent if movement is successful" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMovementPackets.cs", + "line": 83 + } + } + ] +} diff --git a/docs/packets/incoming/player.json b/docs/packets/incoming/player.json new file mode 100644 index 000000000..c21245b04 --- /dev/null +++ b/docs/packets/incoming/player.json @@ -0,0 +1,989 @@ +{ + "category": "Player", + "packets": [ + { + "id": "0x01", + "name": "Disconnect", + "description": "Client sends disconnect notification.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Packet identifier" + }, + { + "name": "Minus One", + "type": "int", + "size": 4, + "value": "0xFFFFFFFF", + "description": "Always -1" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 317 + } + }, + { + "id": "0x05", + "name": "Attack Request", + "description": "Client requests to attack a mobile.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x05", + "description": "Packet identifier" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile to attack" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 69 + } + }, + { + "id": "0x12", + "name": "Text Command", + "description": "Client sends text-based commands for skills, spells, virtues, etc.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x12", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Type of text command", + "values": [ + { + "value": "0x24", + "name": "Use Skill", + "description": "Use a skill by ID" + }, + { + "value": "0x27", + "name": "Cast Spell From Book", + "description": "Cast spell from spellbook" + }, + { + "value": "0x2F", + "name": "Old Scroll Click", + "description": "Old scroll double-click" + }, + { + "value": "0x43", + "name": "Open Spellbook", + "description": "Open spellbook of type" + }, + { + "value": "0x56", + "name": "Cast Spell Macro", + "description": "Cast spell from macro" + }, + { + "value": "0x58", + "name": "Open Door", + "description": "Open door macro" + }, + { + "value": "0xC7", + "name": "Animate", + "description": "Play animation" + }, + { + "value": "0xF4", + "name": "Invoke Virtue", + "description": "Invoke virtue from macro" + } + ] + }, + { + "name": "Command", + "type": "ascii-t", + "description": "Command-specific text (skill ID, spell ID, etc.)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 119 + } + }, + { + "id": "0x22", + "name": "Resynchronize", + "description": "Client requests full world state resync.", + "direction": "incoming", + "noMerge": true, + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x22", + "description": "Packet identifier" + }, + { + "name": "Padding", + "type": "ushort", + "size": 2, + "description": "Unused padding" + } + ], + "notes": "Not related to outgoing 0x22 (Movement Acknowledgment) despite sharing the same packet ID.", + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 349 + } + }, + { + "id": "0x2C", + "name": "Death Status Response", + "description": "Client acknowledges death status packet. Currently ignored by server.", + "direction": "incoming", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x2C", + "description": "Packet identifier" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 58 + } + }, + { + "id": "0x34", + "name": "Mobile Query", + "description": "Client queries information about a mobile (stats or skills).", + "direction": "incoming", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x34", + "description": "Packet identifier" + }, + { + "name": "Pattern", + "type": "uint", + "size": 4, + "value": "0xEDEDEDED", + "description": "Fixed pattern" + }, + { + "name": "Query Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Type of query", + "values": [ + { + "value": "0x04", + "name": "Stats", + "description": "Request mobile stats" + }, + { + "value": "0x05", + "name": "Skills", + "description": "Request mobile skills" + } + ] + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile to query" + } + ], + "related": [ + { + "id": "0x11", + "relationship": "response", + "note": "Mobile Status packet sent in response to stats query" + }, + { + "id": "0x3A", + "relationship": "response", + "note": "Skills Update sent in response to skills query" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 376 + } + }, + { + "id": "0x3A", + "name": "Change Skill Lock", + "description": "Client changes the lock state of a skill.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3A", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Skill Index", + "type": "short", + "size": 2, + "description": "Skill index to change" + }, + { + "name": "Lock State", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "New lock state", + "values": [ + { + "value": 0, + "name": "Up", + "description": "Skill gains enabled" + }, + { + "value": 1, + "name": "Down", + "description": "Skill decreases enabled" + }, + { + "value": 2, + "name": "Locked", + "description": "Skill locked at current value" + } + ] + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 331 + } + }, + { + "id": "0x72", + "name": "Set War Mode", + "description": "Client toggles war/peace mode.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x72", + "description": "Packet identifier" + }, + { + "name": "Warmode", + "type": "bool", + "size": 1, + "description": "True = war mode, False = peace mode" + }, + { + "name": "Padding", + "type": "byte", + "size": 3, + "description": "Unused padding (0x00, 0x32, 0x00)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 343 + } + }, + { + "id": "0x73", + "name": "Ping Request", + "description": "Client sends ping for latency measurement.", + "direction": "incoming", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x73", + "description": "Packet identifier" + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Ping sequence number" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 366 + } + }, + { + "id": "0x7D", + "name": "Menu Response", + "description": "Client responds to a displayed item menu.", + "direction": "incoming", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x7D", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Menu dialog serial" + }, + { + "name": "Menu ID", + "type": "short", + "size": 2, + "description": "Menu ID (unused in implementation)" + }, + { + "name": "Index", + "type": "short", + "size": 2, + "description": "Selected item index (1-based, 0 = cancel)" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Item graphic ID of selection" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Hue of selection" + } + ], + "related": [ + { + "id": "0x7C", + "relationship": "request", + "note": "Display Item List Menu packet" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 287 + } + }, + { + "id": "0x95", + "name": "Hue Picker Response", + "description": "Client responds to a hue picker dialog.", + "direction": "incoming", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x95", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Hue picker serial" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Item ID (unused)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Selected hue (masked with 0x3FFF)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 86 + } + }, + { + "id": "0x9A", + "name": "ASCII Prompt Response", + "description": "Client responds to an ASCII text prompt.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Menu"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x9A", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Prompt serial" + }, + { + "name": "Prompt ID", + "type": "int", + "size": 4, + "description": "Prompt ID" + }, + { + "name": "Type", + "type": "int", + "size": 4, + "description": "Response type: 0 = cancel, other = submit" + }, + { + "name": "Text", + "type": "ascii-t", + "description": "Response text (max 128 chars)" + } + ], + "related": [ + { + "id": "0xC2", + "relationship": "request", + "note": "Unicode Prompt packet that triggered this response" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 214 + } + }, + { + "id": "0x9B", + "name": "Help Request", + "description": "Client requests help/GM assistance.", + "direction": "incoming", + "isDynamic": false, + "size": 258, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x9B", + "description": "Packet identifier" + }, + { + "name": "Data", + "type": "byte[]", + "size": 257, + "description": "Help request data (format TBD)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 338 + } + }, + { + "id": "0xA4", + "name": "System Info", + "description": "Client sends system/hardware information.", + "direction": "incoming", + "isDynamic": false, + "size": 149, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA4", + "description": "Packet identifier" + }, + { + "name": "Unknown1", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "ushort", + "size": 2, + "description": "Unknown" + }, + { + "name": "Unknown3", + "type": "byte", + "size": 1, + "description": "Unknown" + }, + { + "name": "String1", + "type": "ascii", + "size": 32, + "description": "System string 1" + }, + { + "name": "String2", + "type": "ascii", + "size": 32, + "description": "System string 2" + }, + { + "name": "String3", + "type": "ascii", + "size": 32, + "description": "System string 3" + }, + { + "name": "String4", + "type": "ascii", + "size": 32, + "description": "System string 4" + }, + { + "name": "Unknown4", + "type": "ushort", + "size": 2, + "description": "Unknown" + }, + { + "name": "Unknown5", + "type": "ushort", + "size": 2, + "description": "Unknown" + }, + { + "name": "Unknown6", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown7", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Unknown8", + "type": "int", + "size": 4, + "description": "Unknown" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 103 + } + }, + { + "id": "0xA7", + "name": "Request Scroll Window", + "description": "Client requests a tips/scroll window.", + "direction": "incoming", + "isDynamic": false, + "size": 4, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA7", + "description": "Packet identifier" + }, + { + "name": "Last Tip", + "type": "short", + "size": 2, + "description": "Last tip ID viewed" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Scroll type" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 63 + } + }, + { + "id": "0xC2", + "name": "Unicode Prompt Response", + "description": "Client responds to a Unicode text prompt.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "tags": ["Menu"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC2", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Prompt serial" + }, + { + "name": "Prompt ID", + "type": "int", + "size": 4, + "description": "Prompt ID" + }, + { + "name": "Type", + "type": "int", + "size": 4, + "description": "Response type: 0 = cancel, other = submit" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., \u0027ENU\u0027)" + }, + { + "name": "Text", + "type": "utf16le-t", + "description": "Response text (max 128 chars)" + } + ], + "related": [ + { + "id": "0xC2", + "direction": "outgoing", + "relationship": "request", + "note": "Unicode Prompt packet that triggered this response" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 250 + } + }, + { + "id": "0xC8", + "name": "Set Update Range", + "description": "Client requests to change update range. Server ignores and sends back fixed range.", + "direction": "incoming", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC8", + "description": "Packet identifier" + }, + { + "name": "Range", + "type": "byte", + "size": 1, + "description": "Requested update range (ignored)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 371 + } + }, + { + "id": "0xD0", + "name": "Configuration File", + "description": "Client sends configuration data. Currently ignored by server.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD0", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Data", + "type": "byte[]", + "description": "Configuration data (ignored)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 322 + } + }, + { + "id": "0xD1", + "name": "Logout Request", + "description": "Client requests to logout.", + "direction": "incoming", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD1", + "description": "Packet identifier" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown (typically 0x01)" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 326 + } + }, + { + "id": "0xF4", + "name": "Crash Report", + "description": "Client sends crash/error report.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF4", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Client Major", + "type": "byte", + "size": 1, + "description": "Client major version" + }, + { + "name": "Client Minor", + "type": "byte", + "size": 1, + "description": "Client minor version" + }, + { + "name": "Client Rev", + "type": "byte", + "size": 1, + "description": "Client revision" + }, + { + "name": "Client Pat", + "type": "byte", + "size": 1, + "description": "Client patch" + }, + { + "name": "X", + "type": "ushort", + "size": 2, + "description": "Player X coordinate at crash" + }, + { + "name": "Y", + "type": "ushort", + "size": 2, + "description": "Player Y coordinate at crash" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Player Z coordinate at crash" + }, + { + "name": "Map", + "type": "byte", + "size": 1, + "description": "Map ID at crash" + }, + { + "name": "Account Name", + "type": "ascii", + "size": 32, + "description": "Account name" + }, + { + "name": "Character Name", + "type": "ascii", + "size": 32, + "description": "Character name" + }, + { + "name": "IP Address", + "type": "ascii", + "size": 15, + "description": "Client IP address" + }, + { + "name": "Unknown1", + "type": "int", + "size": 4, + "description": "Unknown" + }, + { + "name": "Exception Code", + "type": "int", + "size": 4, + "description": "Exception code" + }, + { + "name": "Process Name", + "type": "ascii", + "size": 100, + "description": "Process name" + }, + { + "name": "Report Text", + "type": "ascii", + "size": 100, + "description": "Report text" + }, + { + "name": "Terminator", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Null terminator" + }, + { + "name": "Offset", + "type": "int", + "size": 4, + "description": "Crash offset" + }, + { + "name": "Stack Count", + "type": "byte", + "size": 1, + "description": "Number of stack trace entries" + }, + { + "name": "Stack Addresses", + "type": "loop", + "loop": { + "countField": "stackCount", + "fields": [ + { + "name": "Address", + "type": "int", + "size": 4, + "description": "Stack frame address" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 413 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/securetrade.json b/docs/packets/incoming/securetrade.json new file mode 100644 index 000000000..e0b26a90b --- /dev/null +++ b/docs/packets/incoming/securetrade.json @@ -0,0 +1,144 @@ +{ + "category": "Secure Trade", + "packets": [ + { + "id": "0x6F", + "name": "Secure Trade", + "description": "Client interacts with a secure trade window.", + "direction": "incoming", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Cancel Trade", + "condition": "action == Cancel (1)", + "size": 8, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Action", + "type": "byte", + "size": 1, + "value": "1", + "description": "Cancel action" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of the trade container" + } + ] + }, + { + "name": "Toggle Accept", + "condition": "action == Check (2)", + "size": 12, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Action", + "type": "byte", + "size": 1, + "value": "2", + "description": "Check/toggle action" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of the trade container" + }, + { + "name": "Accepted", + "type": "bool", + "size": 4, + "description": "True if accepting the trade" + } + ] + }, + { + "name": "Update Gold/Platinum", + "condition": "action == UpdateGold (3)", + "size": 16, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Action", + "type": "byte", + "size": 1, + "value": "3", + "description": "Update gold action" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of the trade container" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Gold amount to trade" + }, + { + "name": "Platinum", + "type": "int", + "size": 4, + "description": "Platinum amount to trade" + } + ] + } + ], + "related": [ + { + "id": "0x6F", + "direction": "outgoing", + "relationship": "response", + "note": "Server sends trade window updates" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 93 + } + } + ] +} diff --git a/docs/packets/incoming/targeting.json b/docs/packets/incoming/targeting.json new file mode 100644 index 000000000..9b56a84e4 --- /dev/null +++ b/docs/packets/incoming/targeting.json @@ -0,0 +1,117 @@ +{ + "category": "Targeting", + "packets": [ + { + "id": "0x6C", + "name": "Target Response", + "description": "Client responds to a target cursor request.", + "direction": "incoming", + "isDynamic": false, + "size": 19, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6C", + "description": "Packet identifier" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Target type", + "values": [ + { + "value": 0, + "name": "Object", + "description": "Targeting a specific object (mobile/item)" + }, + { + "value": 1, + "name": "Location", + "description": "Targeting a location/tile" + } + ] + }, + { + "name": "Target ID", + "type": "int", + "size": 4, + "description": "Target cursor ID to match request" + }, + { + "name": "Flags", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Target flags", + "values": [ + { + "value": 0, + "name": "Neutral", + "description": "Neutral targeting" + }, + { + "value": 1, + "name": "Harmful", + "description": "Harmful action" + }, + { + "value": 2, + "name": "Beneficial", + "description": "Beneficial action" + }, + { + "value": 3, + "name": "Cancel", + "description": "Targeting canceled" + } + ] + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of targeted object (0 for ground)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate (-1 if canceled)" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate (-1 if canceled)" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown (typically 0)" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Target Z coordinate" + }, + { + "name": "Graphic", + "type": "ushort", + "size": 2, + "description": "Graphic ID of targeted tile (0 for land)" + } + ], + "notes": "If x == -1 \u0026\u0026 y == -1 \u0026\u0026 serial is invalid, user pressed Escape to cancel targeting.", + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingTargetingPackets.cs", + "line": 28 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/incoming/vendor.json b/docs/packets/incoming/vendor.json new file mode 100644 index 000000000..48e654674 --- /dev/null +++ b/docs/packets/incoming/vendor.json @@ -0,0 +1,145 @@ +{ + "category": "Vendor", + "packets": [ + { + "id": "0x3B", + "name": "Vendor Buy Reply", + "description": "Client confirms items to purchase from a vendor.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3B", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Vendor Serial", + "type": "uint", + "size": 4, + "description": "Serial of the vendor" + }, + { + "name": "Flag", + "type": "byte", + "size": 1, + "description": "0x00 = buy, 0x02 = cancel" + }, + { + "name": "Items", + "type": "loop", + "loop": { + "untilEnd": true, + "fields": [ + { + "name": "Layer", + "type": "byte", + "size": 1, + "description": "Layer/container index" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of item to buy" + }, + { + "name": "Amount", + "type": "short", + "size": 2, + "description": "Amount to purchase" + } + ] + } + } + ], + "related": [ + { + "id": "0x74", + "relationship": "request", + "note": "Vendor Buy List packet that initiated this" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingVendorPackets.cs", + "line": 25 + } + }, + { + "id": "0x9F", + "name": "Vendor Sell Reply", + "description": "Client confirms items to sell to a vendor.", + "direction": "incoming", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x9F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Vendor Serial", + "type": "uint", + "size": 4, + "description": "Serial of the vendor" + }, + { + "name": "Item Count", + "type": "ushort", + "size": 2, + "description": "Number of items to sell" + }, + { + "name": "Items", + "type": "loop", + "loop": { + "countField": "itemCount", + "fields": [ + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of item to sell" + }, + { + "name": "Amount", + "type": "short", + "size": 2, + "description": "Amount to sell" + } + ] + } + } + ], + "related": [ + { + "id": "0x9E", + "relationship": "request", + "note": "Vendor Sell List packet that initiated this" + } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingVendorPackets.cs", + "line": 26 + } + } + ] +} diff --git a/docs/packets/outgoing/account.json b/docs/packets/outgoing/account.json new file mode 100644 index 000000000..b7f5d7274 --- /dev/null +++ b/docs/packets/outgoing/account.json @@ -0,0 +1,1181 @@ +{ + "category": "Account", + "packets": [ + { + "id": "0x82", + "name": "Account Login Rejected", + "description": "Sent when account login fails. Contains the reason for rejection.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x82", + "description": "Packet identifier" + }, + { + "name": "Reason", + "type": "enum", + "size": 1, + "description": "Rejection reason code", + "values": [ + { "value": "0", "name": "Invalid", "description": "Invalid credentials" }, + { "value": "1", "name": "InUse", "description": "Account already in use" }, + { "value": "2", "name": "Blocked", "description": "Account blocked" }, + { "value": "3", "name": "BadPass", "description": "Incorrect password" }, + { "value": "254", "name": "Idle", "description": "Idle timeout" }, + { "value": "255", "name": "BadComm", "description": "Communication error" } + ] + } + ], + "related": [ + { + "id": "0x80", + "relationship": "request", + "note": "The login attempt that failed" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 402 + } + }, + { + "id": "0xA8", + "name": "Account Login Ack (Server List)", + "description": "Sent after successful account login. Contains the list of available game servers.", + "direction": "outgoing", + "isDynamic": true, + "size": "6 + (40 x serverCount)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA8", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "System Info Flag", + "type": "byte", + "size": 1, + "value": "0x5D", + "description": "System info flag" + }, + { + "name": "Server Count", + "type": "ushort", + "size": 2, + "description": "Number of servers in list" + }, + { + "name": "Servers", + "type": "array", + "description": "Server list entries", + "loop": { + "countField": "serverCount", + "fields": [ + { + "name": "Index", + "type": "ushort", + "size": 2, + "description": "Server index" + }, + { + "name": "Name", + "type": "ascii", + "size": 32, + "description": "Server name" + }, + { + "name": "Full Percent", + "type": "byte", + "size": 1, + "description": "Server load percentage" + }, + { + "name": "Timezone", + "type": "sbyte", + "size": 1, + "description": "Server timezone offset" + }, + { + "name": "IP Address", + "type": "uint", + "size": 4, + "description": "Server IP address (IPv4)" + } + ] + } + } + ], + "related": [ + { + "id": "0x80", + "relationship": "request", + "note": "The successful login request" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 411 + } + }, + { + "id": "0x8C", + "name": "Play Server Ack", + "description": "Sent after selecting a server. Contains connection details for the game server.", + "direction": "outgoing", + "isDynamic": false, + "size": 11, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x8C", + "description": "Packet identifier" + }, + { + "name": "IP Address", + "type": "uint", + "size": 4, + "description": "Game server IP address (little-endian)" + }, + { + "name": "Port", + "type": "short", + "size": 2, + "description": "Game server port" + }, + { + "name": "Auth ID", + "type": "int", + "size": 4, + "description": "Authentication ID for game login" + } + ], + "related": [ + { + "id": "0xA0", + "relationship": "request", + "note": "The server selection request" + }, + { + "id": "0x91", + "relationship": "response", + "note": "Client sends game login with this authId" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 447 + } + }, + { + "id": "0xA9", + "name": "Character List", + "description": "Sent after game login. Contains the list of characters on the account and starting city information. Extended format in 7.0.13.0+ includes city coordinates.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "version": "Classic", + "name": "Pre-7.0.13.0 Format", + "condition": "Client version \u003c 7.0.13.0", + "size": "9+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA9", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Char Count", + "type": "byte", + "size": 1, + "description": "Number of character slots (1, 5, 6, or 7)" + }, + { + "name": "Characters", + "type": "loop", + "description": "Character list entries (60 bytes each)", + "loop": { + "countField": "charCount", + "itemSize": 60, + "fields": [ + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name (empty if slot unused)" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Always empty (legacy field)" + } + ] + } + }, + { + "name": "City Count", + "type": "byte", + "size": 1, + "description": "Number of starting cities" + }, + { + "name": "Cities", + "type": "loop", + "description": "Starting city entries (63 bytes each)", + "loop": { + "countField": "cityCount", + "itemSize": 63, + "fields": [ + { + "name": "Index", + "type": "byte", + "size": 1, + "description": "City index" + }, + { + "name": "City Name", + "type": "ascii", + "size": 31, + "description": "City name" + }, + { + "name": "Building Name", + "type": "ascii", + "size": 31, + "description": "Building/tavern name" + } + ] + } + }, + { + "name": "Flags", + "type": "bitfield", + "size": 4, + "description": "Character list flags", + "flags": [ + { + "bit": "0", + "name": "Unknown1", + "description": "Unknown" + }, + { + "bit": "1", + "name": "Overwrite Config", + "description": "Overwrite configuration file" + }, + { + "bit": "2", + "name": "One Character Slot", + "description": "Limit to 1 character slot" + }, + { + "bit": "3", + "name": "Context Menus", + "description": "Enable context menus" + }, + { + "bit": "4", + "name": "Slot Limit", + "description": "Limit character slots" + }, + { + "bit": "5", + "name": "AOS", + "description": "Age of Shadows features" + }, + { + "bit": "6", + "name": "Sixth Character Slot", + "description": "Enable 6th character slot" + }, + { + "bit": "7", + "name": "SE", + "description": "Samurai Empire features" + }, + { + "bit": "8", + "name": "ML", + "description": "Mondain\u0027s Legacy features" + }, + { + "bit": "9", + "name": "Unknown2", + "description": "Unknown" + }, + { + "bit": "10", + "name": "KR", + "description": "Kingdom Reborn features" + }, + { + "bit": "11", + "name": "SA", + "description": "Stygian Abyss features" + }, + { + "bit": "12", + "name": "HS", + "description": "High Seas features" + }, + { + "bit": "13", + "name": "Seventh Character Slot", + "description": "Enable 7th character slot" + }, + { + "bit": "14", + "name": "Unknown3", + "description": "Unknown" + }, + { + "bit": "15", + "name": "New Movement", + "description": "New movement system" + }, + { + "bit": "16", + "name": "New Felucca Areas", + "description": "New Felucca areas" + } + ] + } + ] + }, + { + "version": "NewCharacterList (7.0.13.0+)", + "name": "Extended City Format", + "condition": "Client version \u003e= 7.0.13.0 (NewCharacterList)", + "size": "11+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA9", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Char Count", + "type": "byte", + "size": 1, + "description": "Number of character slots (1, 5, 6, or 7)" + }, + { + "name": "Characters", + "type": "loop", + "description": "Character list entries (60 bytes each)", + "loop": { + "countField": "charCount", + "itemSize": 60, + "fields": [ + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name (empty if slot unused)" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Always empty (legacy field)" + } + ] + } + }, + { + "name": "City Count", + "type": "byte", + "size": 1, + "description": "Number of starting cities" + }, + { + "name": "Cities", + "type": "loop", + "description": "Starting city entries (89 bytes each, extended format)", + "loop": { + "countField": "cityCount", + "itemSize": 89, + "fields": [ + { + "name": "Index", + "type": "byte", + "size": 1, + "description": "City index" + }, + { + "name": "City Name", + "type": "ascii", + "size": 32, + "description": "City name (1 byte longer than classic)" + }, + { + "name": "Building Name", + "type": "ascii", + "size": 32, + "description": "Building/tavern name (1 byte longer than classic)" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "X coordinate of starting location" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Y coordinate of starting location" + }, + { + "name": "Z", + "type": "int", + "size": 4, + "description": "Z coordinate of starting location" + }, + { + "name": "Map ID", + "type": "int", + "size": 4, + "description": "Map ID for starting location" + }, + { + "name": "Cliloc", + "type": "int", + "size": 4, + "description": "Cliloc ID for city description" + }, + { + "name": "Unknown", + "type": "int", + "size": 4, + "value": "0", + "description": "Unknown (always 0)" + } + ] + } + }, + { + "name": "Flags", + "type": "bitfield", + "size": 4, + "description": "Character list flags (same as classic format)", + "flags": [ + { + "bit": "2", + "name": "One Character Slot", + "description": "Limit to 1 character slot" + }, + { + "bit": "3", + "name": "Context Menus", + "description": "Enable context menus" + }, + { + "bit": "4", + "name": "Slot Limit", + "description": "Limit character slots" + }, + { + "bit": "5", + "name": "AOS", + "description": "Age of Shadows features" + }, + { + "bit": "6", + "name": "Sixth Character Slot", + "description": "Enable 6th character slot" + }, + { + "bit": "7", + "name": "SE", + "description": "Samurai Empire features" + }, + { + "bit": "8", + "name": "ML", + "description": "Mondain\u0027s Legacy features" + }, + { + "bit": "11", + "name": "SA", + "description": "Stygian Abyss features" + }, + { + "bit": "12", + "name": "HS", + "description": "High Seas features" + }, + { + "bit": "13", + "name": "Seventh Character Slot", + "description": "Enable 7th character slot" + } + ] + }, + { + "name": "Last Char Slot", + "type": "short", + "size": 2, + "value": "-1", + "description": "Last played character slot index (-1 if none)" + } + ] + } + ], + "related": [ + { + "id": "0x91", + "relationship": "request", + "note": "Game login request" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 293 + } + }, + { + "id": "0x1B", + "name": "Login Confirmation", + "description": "Sent when entering the world. Confirms the player\u0027s mobile serial and initial position.", + "direction": "outgoing", + "isDynamic": false, + "size": 37, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x1B", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Player mobile serial" + }, + { + "name": "Unknown", + "type": "int", + "size": 4, + "value": "0", + "description": "Unknown (always 0)" + }, + { + "name": "Body", + "type": "short", + "size": 2, + "description": "Player body ID" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "Z coordinate" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Facing direction" + }, + { + "name": "Unknown2", + "type": "byte", + "size": 1, + "value": "0", + "description": "Unknown" + }, + { + "name": "Unknown3", + "type": "int", + "size": 4, + "value": "-1", + "description": "Unknown (always -1)" + }, + { + "name": "Unknown4", + "type": "int", + "size": 4, + "value": "0", + "description": "Unknown" + }, + { + "name": "Map Width", + "type": "short", + "size": 2, + "description": "Map width in tiles" + }, + { + "name": "Map Height", + "type": "short", + "size": 2, + "description": "Map height in tiles" + }, + { + "name": "Unknown5", + "type": "byte[6]", + "size": 6, + "description": "Unknown (zeros)" + } + ], + "related": [ + { + "id": "0x5D", + "relationship": "request", + "note": "Play character request" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 190 + } + }, + { + "id": "0x55", + "name": "Login Complete", + "description": "Final packet in the login sequence. Signals that the client can begin normal gameplay.", + "direction": "outgoing", + "isDynamic": false, + "size": 1, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x55", + "description": "Packet identifier" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 231 + } + }, + { + "id": "0xBD", + "name": "Client Version Request", + "description": "Request for the client to send its version string.", + "direction": "outgoing", + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBD", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0003", + "description": "Packet length" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 112 + }, + "notes": "Same packet ID (0xBD) is used for both request (server) and response (client)." + }, + { + "id": "0xB9", + "name": "Supported Features", + "description": "Informs the client which features are enabled on the server. Feature flags control T2A, LBR, AOS, SE, ML, SA, HS features and character slot limits.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "Classic", + "name": "16-bit Feature Flags", + "condition": "Client without ExtendedSupportedFeatures", + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB9", + "description": "Packet identifier" + }, + { + "name": "Features", + "type": "bitfield", + "size": 2, + "description": "16-bit feature flags bitmask", + "flags": [ + { + "bit": "0", + "name": "T2A", + "description": "The Second Age features" + }, + { + "bit": "1", + "name": "Renaissance", + "description": "Renaissance features" + }, + { + "bit": "2", + "name": "Third Dawn", + "description": "Third Dawn (3D client) features" + }, + { + "bit": "3", + "name": "LBR", + "description": "Lord Blackthorn\u0027s Revenge features" + }, + { + "bit": "4", + "name": "AOS", + "description": "Age of Shadows features" + }, + { + "bit": "5", + "name": "Sixth Character Slot", + "description": "Enable 6th character slot" + }, + { + "bit": "6", + "name": "SE", + "description": "Samurai Empire features" + }, + { + "bit": "7", + "name": "ML", + "description": "Mondain\u0027s Legacy features" + }, + { + "bit": "8", + "name": "Eighth Age", + "description": "Eighth Age splash screen" + }, + { + "bit": "9", + "name": "Ninth Age", + "description": "Ninth Age splash screen" + }, + { + "bit": "10", + "name": "Tenth Age", + "description": "Tenth Age splash screen" + }, + { + "bit": "11", + "name": "Increased Storage", + "description": "Increased storage" + }, + { + "bit": "12", + "name": "Seventh Character Slot", + "description": "Enable 7th character slot" + }, + { + "bit": "13", + "name": "Roleplay Faces", + "description": "Roleplay face selection" + }, + { + "bit": "14", + "name": "Trial Account", + "description": "Trial account flag" + }, + { + "bit": "15", + "name": "Live Account", + "description": "Live (paid) account flag" + } + ] + } + ] + }, + { + "version": "Extended", + "name": "32-bit Feature Flags", + "condition": "Client with ExtendedSupportedFeatures", + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB9", + "description": "Packet identifier" + }, + { + "name": "Features", + "type": "bitfield", + "size": 4, + "description": "32-bit feature flags bitmask (includes all 16-bit flags plus expansion flags)", + "flags": [ + { + "bit": "0", + "name": "T2A", + "description": "The Second Age features" + }, + { + "bit": "1", + "name": "Renaissance", + "description": "Renaissance features" + }, + { + "bit": "2", + "name": "Third Dawn", + "description": "Third Dawn (3D client) features" + }, + { + "bit": "3", + "name": "LBR", + "description": "Lord Blackthorn\u0027s Revenge features" + }, + { + "bit": "4", + "name": "AOS", + "description": "Age of Shadows features" + }, + { + "bit": "5", + "name": "Sixth Character Slot", + "description": "Enable 6th character slot" + }, + { + "bit": "6", + "name": "SE", + "description": "Samurai Empire features" + }, + { + "bit": "7", + "name": "ML", + "description": "Mondain\u0027s Legacy features" + }, + { + "bit": "8", + "name": "Eighth Age", + "description": "Eighth Age splash screen" + }, + { + "bit": "9", + "name": "Ninth Age", + "description": "Ninth Age splash screen" + }, + { + "bit": "10", + "name": "Tenth Age", + "description": "Tenth Age splash screen" + }, + { + "bit": "11", + "name": "Increased Storage", + "description": "Increased storage" + }, + { + "bit": "12", + "name": "Seventh Character Slot", + "description": "Enable 7th character slot" + }, + { + "bit": "13", + "name": "Roleplay Faces", + "description": "Roleplay face selection" + }, + { + "bit": "14", + "name": "Trial Account", + "description": "Trial account flag" + }, + { + "bit": "15", + "name": "Live Account", + "description": "Live (paid) account flag" + }, + { + "bit": "16", + "name": "SA", + "description": "Stygian Abyss features" + }, + { + "bit": "17", + "name": "HS", + "description": "High Seas features" + }, + { + "bit": "18", + "name": "Gothic", + "description": "Gothic housing tiles" + }, + { + "bit": "19", + "name": "Rustic", + "description": "Rustic housing tiles" + }, + { + "bit": "20", + "name": "Jungle", + "description": "Jungle housing tiles" + }, + { + "bit": "21", + "name": "Shadowguard", + "description": "Shadowguard content" + }, + { + "bit": "22", + "name": "TOL", + "description": "Time of Legends features" + }, + { + "bit": "23", + "name": "EJ", + "description": "Endless Journey (F2P) features" + } + ] + } + ] + } + ], + "clientVersion": { + "feature": "ExtendedSupportedFeatures determines which variant is sent" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 140 + } + }, + { + "id": "0x85", + "name": "Character Delete Result", + "description": "Result of a character deletion request.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x85", + "description": "Packet identifier" + }, + { + "name": "Result", + "type": "enum", + "size": 1, + "description": "Deletion result code", + "values": [ + { "value": "0", "name": "PasswordInvalid", "description": "Password is invalid" }, + { "value": "1", "name": "CharNotExist", "description": "Character does not exist" }, + { "value": "2", "name": "CharBeingPlayed", "description": "Character is being played" }, + { "value": "3", "name": "CharTooYoung", "description": "Character too young to delete" }, + { "value": "4", "name": "CharQueued", "description": "Character queued for deletion" }, + { "value": "5", "name": "BadRequest", "description": "Invalid request" } + ] + } + ], + "related": [ + { + "id": "0x83", + "relationship": "request", + "note": "The delete request" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 121 + } + }, + { + "id": "0x53", + "name": "Popup Message", + "description": "Displays a predefined popup message to the client.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x53", + "description": "Packet identifier" + }, + { + "name": "Message ID", + "type": "enum", + "size": 1, + "description": "Predefined message identifier", + "values": [ + { "value": "1", "name": "CharNoExist", "description": "Character does not exist" }, + { "value": "2", "name": "CharExists", "description": "Character already exists" }, + { "value": "5", "name": "CharInWorld", "description": "Character is in world" }, + { "value": "6", "name": "LoginSyncError", "description": "Login synchronization error" }, + { "value": "7", "name": "IdleWarning", "description": "Idle timeout warning" } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 131 + } + }, + { + "id": "0x81", + "name": "Change Character", + "description": "Updates the character list during reconnection. Currently unused.", + "direction": "outgoing", + "isDynamic": true, + "size": "5 + (60 x charCount)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x81", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Char Count", + "type": "ushort", + "size": 2, + "description": "Number of characters" + }, + { + "name": "Characters", + "type": "array", + "description": "Character list entries", + "loop": { + "countField": "charCount", + "fields": [ + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Always empty" + } + ] + } + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 63 + }, + "notes": "Currently unused in ModernUO." + }, + { + "id": "0x86", + "name": "Character List Update", + "description": "Updates the character list after character creation or deletion.", + "direction": "outgoing", + "isDynamic": true, + "size": "4 + (60 x charCount)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x86", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Char Count", + "type": "byte", + "size": 1, + "description": "Number of character slots" + }, + { + "name": "Characters", + "type": "array", + "description": "Character list entries", + "loop": { + "countField": "charCount", + "fields": [ + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Character name (empty if slot unused)" + }, + { + "name": "Password", + "type": "ascii", + "size": 30, + "description": "Always empty" + } + ] + } + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingAccountPackets.cs", + "line": 242 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/arrow.json b/docs/packets/outgoing/arrow.json new file mode 100644 index 000000000..834134715 --- /dev/null +++ b/docs/packets/outgoing/arrow.json @@ -0,0 +1,138 @@ +{ + "category": "Quest", + "packets": [ + { + "id": "0xBA", + "name": "Quest Arrow", + "description": "Sets or cancels the quest tracking arrow on the client.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "name": "Pre-High Seas Set Arrow", + "version": "pre-HS", + "condition": "command == 1 (Set), pre-HighSeas client", + "size": 6, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBA", + "description": "Packet identifier" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Set arrow command" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate" + } + ] + }, + { + "name": "Pre-High Seas Cancel Arrow", + "version": "pre-HS", + "condition": "command == 0 (Cancel), pre-HighSeas client", + "size": 6, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBA", + "description": "Packet identifier" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Cancel arrow command" + }, + { + "name": "X", + "type": "short", + "size": 2, + "value": "-1", + "description": "X coordinate (-1)" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "value": "-1", + "description": "Y coordinate (-1)" + } + ] + }, + { + "name": "High Seas", + "version": "HS+", + "condition": "HighSeas client (7.0.9.0+)", + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBA", + "description": "Packet identifier" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "description": "Command (0 = cancel, 1 = set)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of tracked target" + } + ] + } + ], + "related": [ + { + "id": "0xBF/0x07", + "relationship": "request", + "note": "Quest Arrow Click from client" + } + ], + "clientVersion": { + "feature": "HighSeas (7.0.9.0+) adds target serial" + }, + "source": { + "file": "Projects/UOContent/Skills/Tracking/OutgoingArrowPackets.cs", + "line": 29 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/assistant.json b/docs/packets/outgoing/assistant.json new file mode 100644 index 000000000..634563aac --- /dev/null +++ b/docs/packets/outgoing/assistant.json @@ -0,0 +1,75 @@ +{ + "category": "Assistant", + "packets": [ + { + "id": "0xF0", + "name": "Assistant Handshake", + "description": "Server sends handshake to negotiate assistant features with Razor-style clients. Contains disallowed feature flags.", + "direction": "outgoing", + "isDynamic": false, + "size": 12, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF0", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x000C", + "description": "Packet length (12)" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0xFE", + "description": "Handshake command" + }, + { + "name": "Disallowed Features", + "type": "ulong", + "size": 8, + "description": "Bitmask of disallowed assistant features" + } + ], + "notes": "Used for assistant negotiation with Razor Community Edition and similar clients. If negotiation fails within 30 seconds, the server may kick the player.", + "source": { + "file": "Projects/UOContent/Assistants/AssistantHandler.cs", + "line": 132 + } + }, + { + "id": "0xBE", + "name": "Assistant Version Request", + "description": "Server requests assistant version information from the client.", + "direction": "outgoing", + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBE", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0003", + "description": "Packet length (3)" + } + ], + "source": { + "file": "Projects/UOContent/Assistants/AssistantHandler.cs", + "line": 122 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/boat.json b/docs/packets/outgoing/boat.json new file mode 100644 index 000000000..db1a96a9e --- /dev/null +++ b/docs/packets/outgoing/boat.json @@ -0,0 +1,182 @@ +{ + "category": "Boat", + "packets": [ + { + "id": "0xF6", + "name": "Boat Move (High Seas)", + "description": "Sent when a boat moves, containing the boat\u0027s new position and all entities on board with their updated positions.", + "direction": "outgoing", + "isDynamic": true, + "size": "18 + (entityCount x 10)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF6", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Boat Serial", + "type": "uint", + "size": 4, + "description": "Serial of the boat" + }, + { + "name": "Speed", + "type": "byte", + "size": 1, + "description": "Boat movement speed" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Movement direction (0-7)" + }, + { + "name": "Facing", + "type": "byte", + "size": 1, + "description": "Boat facing direction" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Boat X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Boat Y coordinate" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "Boat Z coordinate" + }, + { + "name": "Entity Count", + "type": "short", + "size": 2, + "description": "Number of entities on boat (max 65535)" + }, + { + "name": "Entities", + "type": "array", + "description": "Entities on the boat with their positions", + "loop": { + "countField": "entityCount", + "fields": [ + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Entity X coordinate (boat offset applied)" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Entity Y coordinate (boat offset applied)" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "Entity Z coordinate" + } + ] + } + } + ], + "clientVersion": { + "feature": "HighSeas" + }, + "source": { + "file": "Projects/UOContent/Multis/Boats/BoatPackets.cs", + "line": 27 + }, + "notes": "High Seas expansion only. Entities include mobiles and items on the boat. Coordinates include the boat\u0027s movement offset." + }, + { + "id": "0xF7", + "name": "Packet Container", + "description": "Container packet for batching multiple entity packets. Used for efficient display of boats and other groups of entities.", + "direction": "outgoing", + "isDynamic": true, + "size": "5+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Total packet length" + }, + { + "name": "Packet Count", + "type": "ushort", + "size": 2, + "description": "Number of embedded packets" + }, + { + "name": "Packets", + "type": "array", + "description": "Embedded packets (typically 0xF3 World Entity packets)", + "loop": { + "countField": "packetCount", + "fields": [ + { + "name": "Embedded Packet", + "type": "packet", + "description": "Complete embedded packet (0xF3 World Entity or similar)" + } + ] + } + } + ], + "related": [ + { + "id": "0xF3", + "relationship": "contains", + "note": "Typically contains World Entity packets" + }, + { + "id": "0xF6", + "relationship": "variant", + "note": "Used alongside Move Boat HS for boat display" + } + ], + "clientVersion": { + "feature": "HighSeas" + }, + "notes": "Uses PacketContainerBuilder for dynamic growth when embedding many packets. Minimum packet length is 5 bytes (header only).", + "source": { + "file": "Projects/Server/Network/Packets/PacketContainerBuilder.cs", + "line": 23 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/book.json b/docs/packets/outgoing/book.json new file mode 100644 index 000000000..34e3addd5 --- /dev/null +++ b/docs/packets/outgoing/book.json @@ -0,0 +1,217 @@ +{ + "category": "Book", + "packets": [ + { + "id": "0x66", + "name": "Book Content", + "description": "Sends full book content including all pages and lines.", + "direction": "outgoing", + "isDynamic": true, + "size": "9+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x66", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages" + }, + { + "name": "Pages", + "type": "loop", + "description": "Page contents", + "loop": { + "countField": "pageCount", + "fields": [ + { + "name": "Page Number", + "type": "ushort", + "size": 2, + "description": "Page number (1-indexed)" + }, + { + "name": "Line Count", + "type": "ushort", + "size": 2, + "description": "Number of lines on page" + }, + { + "name": "Lines", + "type": "loop", + "description": "Lines on the page", + "loop": { + "countField": "lineCount", + "fields": [ + { + "name": "Text", + "type": "utf8-t", + "description": "Line text" + } + ] + } + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Items/Books/BookPackets.cs", + "line": 136 + } + }, + { + "id": "0xD4", + "name": "Book Header", + "description": "Sends book cover information (title, author, writable status).", + "direction": "outgoing", + "isDynamic": true, + "size": "17+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD4", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book" + }, + { + "name": "Flag On", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Flag on (always 1)" + }, + { + "name": "Writable", + "type": "bool", + "size": 1, + "description": "True if book is writable and in range" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages" + }, + { + "name": "Title Length", + "type": "ushort", + "size": 2, + "description": "Length of title + 1 (for null)" + }, + { + "name": "Title", + "type": "utf8-t", + "description": "Book title" + }, + { + "name": "Author Length", + "type": "ushort", + "size": 2, + "description": "Length of author + 1 (for null)" + }, + { + "name": "Author", + "type": "utf8-t", + "description": "Book author" + } + ], + "related": [ + { + "id": "0x93", + "relationship": "variant", + "note": "Old Book Header format (outgoing)" + } + ], + "source": { + "file": "Projects/UOContent/Items/Books/BookPackets.cs", + "line": 184 + } + }, + { + "id": "0x93", + "name": "Old Book Header", + "description": "Old format for book cover (fixed-size ASCII strings).", + "direction": "outgoing", + "isDynamic": false, + "size": 99, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x93", + "description": "Packet identifier" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the book" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Book flags" + }, + { + "name": "Page Count", + "type": "ushort", + "size": 2, + "description": "Number of pages" + }, + { + "name": "Title", + "type": "ascii", + "size": 60, + "description": "Book title (fixed 60 bytes)" + }, + { + "name": "Author", + "type": "ascii", + "size": 30, + "description": "Book author (fixed 30 bytes)" + } + ], + "related": [ + { + "id": "0xD4", + "relationship": "variant", + "note": "New Book Header format (outgoing)" + } + ], + "notes": "Old format used by older clients. Title and author are fixed-size ASCII." + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/bufficon.json b/docs/packets/outgoing/bufficon.json new file mode 100644 index 000000000..3aa402595 --- /dev/null +++ b/docs/packets/outgoing/bufficon.json @@ -0,0 +1,304 @@ +{ + "category": "Buff Icon", + "packets": [ + { + "id": "0xDF", + "name": "Buff/Debuff System", + "description": "Manages buff and debuff icons displayed on the client.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Remove Buff", + "condition": "command == 0 (Remove)", + "size": 15, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "15", + "description": "Packet length" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of the mobile" + }, + { + "name": "Icon ID", + "type": "short", + "size": 2, + "description": "Buff icon ID" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Remove command" + }, + { + "name": "Unused", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + } + ] + }, + { + "name": "Add Buff (No Args)", + "condition": "command == 1 (Add), no arguments", + "size": 46, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "46", + "description": "Packet length" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of the mobile" + }, + { + "name": "Icon ID", + "type": "short", + "size": 2, + "description": "Buff icon ID" + }, + { + "name": "Command1", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Add command" + }, + { + "name": "Unused1", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Icon Id2", + "type": "short", + "size": 2, + "description": "Buff icon ID (repeated)" + }, + { + "name": "Command2", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Add command (repeated)" + }, + { + "name": "Unused2", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Duration", + "type": "short", + "size": 2, + "description": "Duration in seconds" + }, + { + "name": "Padding", + "type": "byte[]", + "size": 3, + "description": "Padding (zeros)" + }, + { + "name": "Title Cliloc", + "type": "int", + "size": 4, + "description": "Title cliloc number" + }, + { + "name": "Secondary Cliloc", + "type": "int", + "size": 4, + "description": "Secondary cliloc number" + }, + { + "name": "Empty Args", + "type": "byte[]", + "size": 10, + "description": "Empty arguments (zeros)" + } + ] + }, + { + "name": "Add Buff (With Args)", + "condition": "command == 1 (Add), with arguments", + "size": "52 + (args.Length x 2)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of the mobile" + }, + { + "name": "Icon ID", + "type": "short", + "size": 2, + "description": "Buff icon ID" + }, + { + "name": "Command1", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Add command" + }, + { + "name": "Unused1", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Icon Id2", + "type": "short", + "size": 2, + "description": "Buff icon ID (repeated)" + }, + { + "name": "Command2", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Add command (repeated)" + }, + { + "name": "Unused2", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Duration", + "type": "short", + "size": 2, + "description": "Duration in seconds" + }, + { + "name": "Padding", + "type": "byte[]", + "size": 3, + "description": "Padding (zeros)" + }, + { + "name": "Title Cliloc", + "type": "int", + "size": 4, + "description": "Title cliloc number" + }, + { + "name": "Secondary Cliloc", + "type": "int", + "size": 4, + "description": "Secondary cliloc number" + }, + { + "name": "Unused3", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Has Args", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Has arguments flag" + }, + { + "name": "Unused4", + "type": "ushort", + "size": 2, + "value": "0", + "description": "Unused" + }, + { + "name": "Tab Prefix", + "type": "utf16le", + "size": 2, + "value": "\\t", + "description": "Tab character prefix" + }, + { + "name": "Arguments", + "type": "utf16le-t", + "description": "Cliloc arguments" + }, + { + "name": "Has Args2", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Has arguments flag (repeated)" + }, + { + "name": "Unused5", + "type": "ushort", + "size": 2, + "value": "0", + "description": "Unused" + } + ] + } + ], + "clientVersion": { + "min": "5.0.2b", + "feature": "BuffIcon" + }, + "source": { + "file": "Projects/UOContent/Engines/BuffIcons/BuffIconPackets.cs", + "line": 8 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/bulletinboard.json b/docs/packets/outgoing/bulletinboard.json new file mode 100644 index 000000000..9225a639f --- /dev/null +++ b/docs/packets/outgoing/bulletinboard.json @@ -0,0 +1,279 @@ +{ + "category": "Bulletin Board", + "packets": [ + { + "id": "0x71", + "name": "Bulletin Board", + "description": "Bulletin board display and message packets.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Display Board", + "version": "0x00", + "condition": "command == 0x00", + "size": 38, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "38", + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Display board command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Board Name", + "type": "utf8", + "size": 30, + "description": "Board name (null-padded to 30 bytes)" + } + ] + }, + { + "name": "Message Header", + "version": "0x01", + "condition": "command == 0x01", + "size": "22+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Message header command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Message Serial", + "type": "uint", + "size": 4, + "description": "Serial of the message" + }, + { + "name": "Thread Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent thread (0 if root)" + }, + { + "name": "Poster Length", + "type": "byte", + "size": 1, + "description": "Length of poster name" + }, + { + "name": "Poster", + "type": "utf8-t", + "description": "Poster name" + }, + { + "name": "Subject Length", + "type": "byte", + "size": 1, + "description": "Length of subject" + }, + { + "name": "Subject", + "type": "utf8-t", + "description": "Message subject" + }, + { + "name": "Time Length", + "type": "byte", + "size": 1, + "description": "Length of time string" + }, + { + "name": "Time", + "type": "utf8-t", + "description": "Posted time string" + } + ] + }, + { + "name": "Message Content", + "version": "0x02", + "condition": "command == 0x02", + "size": "22+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x71", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x02", + "description": "Message content command" + }, + { + "name": "Board Serial", + "type": "uint", + "size": 4, + "description": "Serial of the bulletin board" + }, + { + "name": "Message Serial", + "type": "uint", + "size": 4, + "description": "Serial of the message" + }, + { + "name": "Poster Length", + "type": "byte", + "size": 1, + "description": "Length of poster name" + }, + { + "name": "Poster", + "type": "utf8-t", + "description": "Poster name" + }, + { + "name": "Subject Length", + "type": "byte", + "size": 1, + "description": "Length of subject" + }, + { + "name": "Subject", + "type": "utf8-t", + "description": "Message subject" + }, + { + "name": "Time Length", + "type": "byte", + "size": 1, + "description": "Length of time string" + }, + { + "name": "Time", + "type": "utf8-t", + "description": "Posted time string" + }, + { + "name": "Poster Body", + "type": "short", + "size": 2, + "description": "Poster body graphic" + }, + { + "name": "Poster Hue", + "type": "short", + "size": 2, + "description": "Poster body hue" + }, + { + "name": "Equip Count", + "type": "byte", + "size": 1, + "description": "Number of equipment items" + }, + { + "name": "Equipment", + "type": "loop", + "description": "Poster\u0027s equipment", + "loop": { + "countField": "equipCount", + "fields": [ + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Equipment item graphic" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Equipment hue" + } + ] + } + }, + { + "name": "Line Count", + "type": "byte", + "size": 1, + "description": "Number of text lines" + }, + { + "name": "Lines", + "type": "loop", + "description": "Message lines", + "loop": { + "countField": "lineCount", + "fields": [ + { + "name": "Line Length", + "type": "byte", + "size": 1, + "description": "Line length" + }, + { + "name": "Line", + "type": "utf8", + "description": "Line text with 2-byte terminator (old client bug)" + } + ] + } + } + ] + } + ], + "source": { + "file": "Projects/UOContent/Items/Bulletin Boards/BulletinBoardPackets.cs", + "line": 168 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/chat.json b/docs/packets/outgoing/chat.json new file mode 100644 index 000000000..3dec3964c --- /dev/null +++ b/docs/packets/outgoing/chat.json @@ -0,0 +1,69 @@ +{ + "category": "Chat", + "packets": [ + { + "id": "0xB2", + "name": "Chat Message", + "description": "Server sends chat system messages and commands to the client.", + "direction": "outgoing", + "isDynamic": true, + "size": "13+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB2", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "description": "Chat command number (original number minus 20)" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., \u0027enu\u0027 for English)" + }, + { + "name": "Param 1", + "type": "utf16be-t", + "description": "First parameter (Big Endian Unicode, null-terminated)" + }, + { + "name": "Param 2", + "type": "utf16be-t", + "description": "Second parameter (Big Endian Unicode, null-terminated)" + } + ], + "related": [ + { + "id": "0xB3", + "direction": "incoming", + "relationship": "request", + "note": "Client sends Chat Action" + }, + { + "id": "0xB5", + "direction": "incoming", + "relationship": "request", + "note": "Client sends Open Chat Window Request" + } + ], + "notes": "Part of the in-game chat system. Command numbers are offset by -20 from original values.", + "source": { + "file": "Projects/UOContent/Engines/Chat/ChatPackets.cs", + "line": 104 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/combat.json b/docs/packets/outgoing/combat.json new file mode 100644 index 000000000..99dbff07e --- /dev/null +++ b/docs/packets/outgoing/combat.json @@ -0,0 +1,120 @@ +{ + "category": "Combat", + "packets": [ + { + "id": "0x2F", + "name": "Swing", + "description": "Notifies client of a melee swing between two mobiles.", + "direction": "outgoing", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x2F", + "description": "Packet identifier" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Attacker Serial", + "type": "uint", + "size": 4, + "description": "Serial of attacker" + }, + { + "name": "Defender Serial", + "type": "uint", + "size": 4, + "description": "Serial of defender" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs", + "line": 23 + } + }, + { + "id": "0x72", + "name": "Set War Mode", + "description": "Sets the client\u0027s war/peace mode state.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x72", + "description": "Packet identifier" + }, + { + "name": "Warmode", + "type": "bool", + "size": 1, + "description": "True = war mode, False = peace mode" + }, + { + "name": "Unknown1", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "byte", + "size": 1, + "value": "0x32", + "description": "Unknown (50)" + }, + { + "name": "Unknown3", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs", + "line": 40 + } + }, + { + "id": "0xAA", + "name": "Change Combatant", + "description": "Notifies client of current combat target.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xAA", + "description": "Packet identifier" + }, + { + "name": "Combatant Serial", + "type": "uint", + "size": 4, + "description": "Serial of current combatant (0 = none)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs", + "line": 43 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/container.json b/docs/packets/outgoing/container.json new file mode 100644 index 000000000..e159ced9a --- /dev/null +++ b/docs/packets/outgoing/container.json @@ -0,0 +1,582 @@ +{ + "category": "Container", + "packets": [ + { + "id": "0x24", + "name": "Display Container", + "description": "Opens a container gump on the client.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "pre-HighSeas", + "name": "Classic", + "size": 7, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x24", + "description": "Packet identifier" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of the container" + }, + { + "name": "Gump ID", + "type": "ushort", + "size": 2, + "description": "Gump graphic ID" + } + ] + }, + { + "version": "HighSeas+", + "name": "High Seas Extended", + "condition": "Client version \u003e= 7.0.9.0 (HighSeas)", + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x24", + "description": "Packet identifier" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of the container" + }, + { + "name": "Gump ID", + "type": "ushort", + "size": 2, + "description": "Gump graphic ID" + }, + { + "name": "Container Type", + "type": "short", + "size": 2, + "value": "0x007D", + "description": "Container type (125)" + } + ] + } + ], + "clientVersion": { + "feature": "HighSeas adds containerType field" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 108 + } + }, + { + "id": "0x25", + "name": "Container Content Update", + "description": "Updates a single item in a container.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "pre-6017", + "name": "Classic", + "size": 20, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x25", + "description": "Packet identifier" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Item ID Offset", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Item ID offset (signed)" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Stack amount" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X position in container" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y position in container" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent container" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue" + } + ] + }, + { + "version": "6017+", + "name": "Container Grid Lines", + "condition": "Client version \u003e= 6.0.1.7 (ContainerGridLines)", + "size": 21, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x25", + "description": "Packet identifier" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Item ID Offset", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Item ID offset (signed)" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Stack amount" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X position in container" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y position in container" + }, + { + "name": "Grid Location", + "type": "byte", + "size": 1, + "description": "Grid slot position" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent container" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue" + } + ] + } + ], + "clientVersion": { + "feature": "ContainerGridLines adds gridLocation byte" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 127 + } + }, + { + "id": "0x3C", + "name": "Container \u0026 Old Spellbook Content", + "description": "Sends full contents of a container. Also used for corpse contents and old-style spellbook content (pre-AOS clients). For AOS+ spellbooks, use 0xBF/0x1B instead.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "tags": ["Spellbook", "Corpse"], + "variants": [ + { + "version": "pre-6017", + "name": "Classic Format", + "condition": "Client version \u003c 6.0.1.7", + "size": "5 + (itemCount x 19)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3C", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Item Count", + "type": "ushort", + "size": 2, + "description": "Number of items" + }, + { + "name": "Items", + "type": "loop", + "description": "Item entries (19 bytes each)", + "loop": { + "countField": "itemCount", + "itemSize": 19, + "fields": [ + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Item ID Offset", + "type": "byte", + "size": 1, + "description": "Item ID offset (signed)" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Stack amount" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X position in container" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y position in container" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent container" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue" + } + ] + } + } + ] + }, + { + "version": "6017+ (ContainerGridLines)", + "name": "Grid Location Format", + "condition": "Client version \u003e= 6.0.1.7 (ContainerGridLines)", + "size": "5 + (itemCount x 20)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3C", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Item Count", + "type": "ushort", + "size": 2, + "description": "Number of items" + }, + { + "name": "Items", + "type": "loop", + "description": "Item entries (20 bytes each)", + "loop": { + "countField": "itemCount", + "itemSize": 20, + "fields": [ + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Item ID Offset", + "type": "byte", + "size": 1, + "description": "Item ID offset (signed)" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Stack amount" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X position in container" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y position in container" + }, + { + "name": "Grid Location", + "type": "byte", + "size": 1, + "description": "Grid slot position in container" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of parent container" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue" + } + ] + } + } + ] + } + ], + "related": [ + { + "id": "0xBF/0x1B", + "relationship": "variant", + "note": "New Spellbook Content for AOS+ clients" + }, + { + "id": "0x89", + "relationship": "related", + "note": "Corpse Equipment (layer mappings for corpse items)" + } + ], + "clientVersion": { + "feature": "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": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 169 + } + }, + { + "id": "0xBF", + "subId": "0x1B", + "name": "New Spellbook Content", + "description": "Sends spellbook contents using AOS format with a 64-bit bitmask of known spells.", + "direction": "outgoing", + "isDynamic": false, + "size": 23, + "tags": ["Spell", "Spellbook", "Extended Commands (0xBF)"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0017", + "description": "Packet length (23)" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x001B", + "description": "Subcommand (New Spellbook Content)" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Command (always 1)" + }, + { + "name": "Book Serial", + "type": "uint", + "size": 4, + "description": "Serial of the spellbook" + }, + { + "name": "Graphic", + "type": "short", + "size": 2, + "description": "Spellbook graphic ID" + }, + { + "name": "Offset", + "type": "short", + "size": 2, + "description": "Spell offset (circle/school start)" + }, + { + "name": "Spell Bits", + "type": "ulong", + "size": 8, + "description": "64-bit mask of known spells (written byte-by-byte, Little Endian)" + } + ], + "related": [ + { + "id": "0x3C", + "relationship": "variant", + "note": "Old Spellbook Content for pre-AOS clients" + } + ], + "clientVersion": { + "min": "5.0.0a", + "feature": "NewSpellbook (Core.AOS \u0026\u0026 ns.NewSpellbook)" + }, + "notes": "Used when Core.AOS \u0026\u0026 ns.NewSpellbook. Otherwise, old 0x3C format is used with spells as pseudo-items.", + "source": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 46 + } + }, + { + "id": "0xF7", + "name": "Packet Container", + "description": "Container packet for batching multiple entity packets. Used for sending groups of related entities efficiently, such as all items and mobiles visible on a boat.", + "direction": "outgoing", + "isDynamic": true, + "size": "5+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Total packet length" + }, + { + "name": "Packet Count", + "type": "ushort", + "size": 2, + "description": "Number of embedded packets" + }, + { + "name": "Packets", + "type": "array", + "description": "Embedded packets (typically 0xF3 World Entity packets)", + "loop": { + "countField": "packetCount", + "fields": [ + { + "name": "Embedded Packet", + "type": "bytes", + "size": "var", + "description": "Complete embedded packet (typically 24-26 byte 0xF3 World Entity)" + } + ] + } + } + ], + "related": [ + { + "id": "0xF3", + "relationship": "contains", + "note": "Typically contains World Entity packets" + } + ], + "clientVersion": { + "min": "7.0.0.0", + "feature": "StygianAbyss" + }, + "notes": "Uses PacketContainerBuilder for efficient dynamic growth. Commonly used by boat system to batch all visible entities on deck.", + "source": { + "file": "Projects/Server/Network/Packets/PacketContainerBuilder.cs", + "line": 9 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/contextmenu.json b/docs/packets/outgoing/contextmenu.json new file mode 100644 index 000000000..e299970ef --- /dev/null +++ b/docs/packets/outgoing/contextmenu.json @@ -0,0 +1,212 @@ +{ + "category": "Context Menu", + "packets": [ + { + "id": "0xBF", + "subId": "0x14", + "name": "Display Context Menu", + "description": "Displays a context menu for an entity.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Old Format", + "version": "0x01", + "condition": "command == 0x01 (pre-NewHaven)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0014", + "description": "Context Menu subcommand" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Old format command" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target entity" + }, + { + "name": "Entry Count", + "type": "byte", + "size": 1, + "description": "Number of menu entries" + }, + { + "name": "Entries", + "type": "loop", + "description": "Menu entries", + "loop": { + "countField": "entryCount", + "fields": [ + { + "name": "Index", + "type": "short", + "size": 2, + "description": "Entry index" + }, + { + "name": "Cliloc Offset", + "type": "ushort", + "size": 2, + "description": "Cliloc number - 3000000" + }, + { + "name": "Flags", + "type": "bitfield", + "size": 2, + "description": "Entry flags", + "flags": [ + { + "bit": "0", + "name": "Disabled", + "description": "Entry is disabled" + }, + { + "bit": "1", + "name": "Arrow", + "description": "Show arrow" + }, + { + "bit": "2", + "name": "Highlighted", + "description": "Entry is highlighted" + }, + { + "bit": "5", + "name": "Colored", + "description": "Entry uses custom color" + } + ] + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text hue (if Colored flag set)", + "condition": "flags \u0026 0x20" + } + ] + } + } + ] + }, + { + "name": "New Format", + "version": "0x02", + "condition": "command == 0x02 (NewHaven+)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0014", + "description": "Context Menu subcommand" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0002", + "description": "New format command" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target entity" + }, + { + "name": "Entry Count", + "type": "byte", + "size": 1, + "description": "Number of menu entries" + }, + { + "name": "Entries", + "type": "loop", + "description": "Menu entries", + "loop": { + "countField": "entryCount", + "fields": [ + { + "name": "Cliloc Number", + "type": "int", + "size": 4, + "description": "Full cliloc number" + }, + { + "name": "Index", + "type": "short", + "size": 2, + "description": "Entry index" + }, + { + "name": "Flags", + "type": "short", + "size": 2, + "description": "Entry flags (see Old Format)" + } + ] + } + } + ] + } + ], + "related": [ + { + "id": "0xBF/0x13", + "relationship": "request", + "note": "Context Menu Request from client" + }, + { + "id": "0xBF/0x15", + "relationship": "response", + "note": "Context Menu Response from client" + } + ], + "clientVersion": { + "feature": "NewHaven clients (6.0.0.0+) use command 0x02" + }, + "source": { + "file": "Projects/UOContent/Context Menus/ContextMenuSystem.cs", + "line": 142 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/corpse.json b/docs/packets/outgoing/corpse.json new file mode 100644 index 000000000..951fe8f09 --- /dev/null +++ b/docs/packets/outgoing/corpse.json @@ -0,0 +1,76 @@ +{ + "category": "Corpse", + "packets": [ + { + "id": "0x89", + "name": "Corpse Equipment", + "description": "Sends the equipment layer mapping for items on a corpse, including virtual hair and facial hair items.", + "direction": "outgoing", + "isDynamic": true, + "size": "8+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x89", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Corpse Serial", + "type": "uint", + "size": 4, + "description": "Serial of the corpse" + }, + { + "name": "Equipment", + "type": "loop", + "description": "Equipment layer mappings (5 bytes each, until terminator)", + "loop": { + "terminator": "Layer == 0", + "fields": [ + { + "name": "Layer", + "type": "byte", + "size": 1, + "description": "Equipment layer + 1 (0 = terminator)" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of item in this layer" + } + ] + } + }, + { + "name": "Terminator", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Layer.Invalid (0) marks end of list" + } + ], + "notes": "Layer values are offset by +1 (e.g., Layer.Hair (0x0B) is sent as 0x0C). Hair and facial hair use virtual serials.", + "related": [ + { + "id": "0x3C", + "direction": "outgoing", + "relationship": "related", + "note": "Container Content (also used for corpse items)" + } + ], + "source": { + "file": "Projects/UOContent/Items/Misc/Corpses/CorpsePackets.cs", + "line": 24 + } + } + ] +} diff --git a/docs/packets/outgoing/damage.json b/docs/packets/outgoing/damage.json new file mode 100644 index 000000000..595710aab --- /dev/null +++ b/docs/packets/outgoing/damage.json @@ -0,0 +1,102 @@ +{ + "category": "Combat", + "packets": [ + { + "id": "0x0B", + "name": "Damage", + "description": "Shows damage dealt to a mobile (client 5.0.0a+).", + "direction": "outgoing", + "isDynamic": false, + "size": 7, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x0B", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of damaged mobile" + }, + { + "name": "Damage", + "type": "ushort", + "size": 2, + "description": "Damage amount (clamped 0-65535)" + } + ], + "clientVersion": { + "min": "5.0.0a", + "feature": "DamagePacket" + }, + "notes": "For pre-5.0.0a clients, use 0xBF/0x22 instead.", + "source": { + "file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs", + "line": 34 + } + }, + { + "id": "0xBF/0x22", + "name": "Damage (Old)", + "description": "Shows damage dealt to a mobile (pre-5.0.0a clients).", + "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": "11", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x22", + "description": "Subcommand (Damage)" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Unknown (always 1)" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of damaged mobile" + }, + { + "name": "Damage", + "type": "byte", + "size": 1, + "description": "Damage amount (clamped 0-255)" + } + ], + "clientVersion": { + "max": "5.0.0a", + "notes": "For clients before DamagePacket feature" + }, + "notes": "Damage is capped at 255 for old clients.", + "source": { + "file": "Projects/Server/Network/Packets/OutgoingDamagePackets.cs", + "line": 40 + } + } + ] +} diff --git a/docs/packets/outgoing/effects.json b/docs/packets/outgoing/effects.json new file mode 100644 index 000000000..2a9710620 --- /dev/null +++ b/docs/packets/outgoing/effects.json @@ -0,0 +1,459 @@ +{ + "category": "Effects", + "packets": [ + { + "id": "0x54", + "name": "Sound Effect", + "description": "Plays a sound effect at a location.", + "direction": "outgoing", + "isDynamic": false, + "size": 12, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x54", + "description": "Packet identifier" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Sound flags" + }, + { + "name": "Sound ID", + "type": "short", + "size": 2, + "description": "Sound effect ID" + }, + { + "name": "Volume", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Volume (unused)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "Z coordinate" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs", + "line": 41 + } + }, + { + "id": "0x70", + "name": "Screen Effect", + "description": "Triggers a screen-wide visual effect (fade in/out).", + "direction": "outgoing", + "isDynamic": false, + "size": 28, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x70", + "description": "Packet identifier" + }, + { + "name": "Effect Type", + "type": "byte", + "size": 1, + "value": "0x04", + "description": "Effect type (4)" + }, + { + "name": "Padding1", + "type": "byte[]", + "size": 8, + "description": "Padding (zeros)" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 2, + "description": "Screen effect type", + "values": [ + { + "value": 0, + "name": "Fade Out", + "description": "Fade screen to black" + }, + { + "value": 1, + "name": "Fade In", + "description": "Fade screen from black" + }, + { + "value": 2, + "name": "Light Flash", + "description": "Light flash effect" + }, + { + "value": 3, + "name": "Fade In Out", + "description": "Fade out then in" + }, + { + "value": 4, + "name": "Darken Screen", + "description": "Darken screen" + } + ] + }, + { + "name": "Padding2", + "type": "byte[]", + "size": 16, + "description": "Padding (zeros)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs", + "line": 322 + } + }, + { + "id": "0xC0", + "name": "Hued Effect", + "description": "Displays a graphical effect with hue and render mode.", + "direction": "outgoing", + "isDynamic": false, + "size": 36, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC0", + "description": "Packet identifier" + }, + { + "name": "Effect Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Effect type", + "values": [ + { + "value": 0, + "name": "Moving", + "description": "Effect moves between two points" + }, + { + "value": 1, + "name": "Lightning", + "description": "Lightning bolt effect" + }, + { + "value": 2, + "name": "Fixed XYZ", + "description": "Effect at fixed location" + }, + { + "value": 3, + "name": "Fixed From", + "description": "Effect attached to source" + } + ] + }, + { + "name": "Source Serial", + "type": "uint", + "size": 4, + "description": "Serial of source entity" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of target entity" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Effect graphic ID" + }, + { + "name": "Src X", + "type": "short", + "size": 2, + "description": "Source X coordinate" + }, + { + "name": "Src Y", + "type": "short", + "size": 2, + "description": "Source Y coordinate" + }, + { + "name": "Src Z", + "type": "sbyte", + "size": 1, + "description": "Source Z coordinate" + }, + { + "name": "Dst X", + "type": "short", + "size": 2, + "description": "Destination X coordinate" + }, + { + "name": "Dst Y", + "type": "short", + "size": 2, + "description": "Destination Y coordinate" + }, + { + "name": "Dst Z", + "type": "sbyte", + "size": 1, + "description": "Destination Z coordinate" + }, + { + "name": "Speed", + "type": "byte", + "size": 1, + "description": "Effect speed" + }, + { + "name": "Duration", + "type": "byte", + "size": 1, + "description": "Effect duration" + }, + { + "name": "Unknown1", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Fixed Direction", + "type": "bool", + "size": 1, + "description": "Fixed direction" + }, + { + "name": "Explode", + "type": "bool", + "size": 1, + "description": "Explode on impact" + }, + { + "name": "Hue", + "type": "int", + "size": 4, + "description": "Effect hue" + }, + { + "name": "Render Mode", + "type": "int", + "size": 4, + "description": "Render mode" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs", + "line": 175 + } + }, + { + "id": "0xC7", + "name": "Particle Effect", + "description": "Displays an advanced particle effect with extended parameters.", + "direction": "outgoing", + "isDynamic": false, + "size": 49, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC7", + "description": "Packet identifier" + }, + { + "name": "Effect Type", + "type": "byte", + "size": 1, + "description": "Effect type (see 0xC0)" + }, + { + "name": "Source Serial", + "type": "uint", + "size": 4, + "description": "Serial of source entity" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of target entity" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Effect graphic ID" + }, + { + "name": "Src X", + "type": "short", + "size": 2, + "description": "Source X coordinate" + }, + { + "name": "Src Y", + "type": "short", + "size": 2, + "description": "Source Y coordinate" + }, + { + "name": "Src Z", + "type": "sbyte", + "size": 1, + "description": "Source Z coordinate" + }, + { + "name": "Dst X", + "type": "short", + "size": 2, + "description": "Destination X coordinate" + }, + { + "name": "Dst Y", + "type": "short", + "size": 2, + "description": "Destination Y coordinate" + }, + { + "name": "Dst Z", + "type": "sbyte", + "size": 1, + "description": "Destination Z coordinate" + }, + { + "name": "Speed", + "type": "byte", + "size": 1, + "description": "Effect speed" + }, + { + "name": "Duration", + "type": "byte", + "size": 1, + "description": "Effect duration" + }, + { + "name": "Unknown1", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Fixed Direction", + "type": "bool", + "size": 1, + "description": "Fixed direction" + }, + { + "name": "Explode", + "type": "bool", + "size": 1, + "description": "Explode on impact" + }, + { + "name": "Hue", + "type": "int", + "size": 4, + "description": "Effect hue" + }, + { + "name": "Render Mode", + "type": "int", + "size": 4, + "description": "Render mode" + }, + { + "name": "Effect", + "type": "short", + "size": 2, + "description": "Particle effect ID" + }, + { + "name": "Explode Effect", + "type": "short", + "size": 2, + "description": "Explosion effect ID" + }, + { + "name": "Explode Sound", + "type": "short", + "size": 2, + "description": "Explosion sound ID" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Associated entity serial" + }, + { + "name": "Layer", + "type": "byte", + "size": 1, + "description": "Effect layer" + }, + { + "name": "Unknown3", + "type": "short", + "size": 2, + "description": "Unknown" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEffectPackets.cs", + "line": 58 + } + } + ] +} diff --git a/docs/packets/outgoing/entity.json b/docs/packets/outgoing/entity.json new file mode 100644 index 000000000..aa089b6d4 --- /dev/null +++ b/docs/packets/outgoing/entity.json @@ -0,0 +1,397 @@ +{ + "category": "Item", + "tags": ["Mobile"], + "packets": [ + { + "id": "0xD6", + "name": "Object Property List", + "description": "Sends the full Object Property List (tooltip) for an entity. Contains a hash for client caching and a list of localized property entries.", + "direction": "outgoing", + "isDynamic": true, + "size": "15+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD6", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Unknown1", + "type": "ushort", + "size": 2, + "value": "0x0001", + "description": "Unknown (always 1)" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + }, + { + "name": "Unknown2", + "type": "ushort", + "size": 2, + "value": "0x0000", + "description": "Unknown (always 0)" + }, + { + "name": "Hash", + "type": "int", + "size": 4, + "description": "XOR hash of all properties (computed with 26-bit mask)" + }, + { + "name": "Properties", + "type": "array", + "description": "Property entries, terminated by number=0", + "loop": { + "terminator": "number == 0", + "fields": [ + { + "name": "Number", + "type": "int", + "size": 4, + "description": "Cliloc number (0 = end of list)" + }, + { + "name": "String Length", + "type": "ushort", + "size": 2, + "description": "Length of arguments in bytes (0 if no arguments)" + }, + { + "name": "Arguments", + "type": "utf16le", + "size": "var", + "description": "Unicode LE string with tab-separated cliloc arguments. Length = String Length field" + } + ] + } + } + ], + "related": [ + { + "id": "0xDC", + "relationship": "notification", + "note": "OPL Info notifies client of hash change, triggering 0xD6 request" + } + ], + "clientVersion": { + "min": "4.0.0a", + "feature": "AOS tooltips" + }, + "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": { + "file": "Projects/Server/PropertyList/ObjectPropertyList.cs", + "line": 19 + } + }, + { + "id": "0x1D", + "name": "Remove Entity", + "description": "Removes an entity (item, mobile, or multi) from the client\u0027s view.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x1D", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity to remove" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs", + "line": 75 + } + }, + { + "id": "0xDC", + "name": "OPL Info (Object Property List)", + "description": "Notifies the client of an entity\u0027s Object Property List hash. Client compares hash to cached version and requests full OPL if different.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDC", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + }, + { + "name": "Hash", + "type": "int", + "size": 4, + "description": "Hash of the Object Property List" + } + ], + "related": [ + { + "id": "0xD6", + "direction": "outgoing", + "relationship": "data", + "note": "Full Object Property List packet" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs", + "line": 33 + } + }, + { + "id": "0xF3", + "name": "World Entity (SA+)", + "description": "Unified entity packet for items, mobiles, and multis. Replaces older 0x1A World Item packet for Stygian Abyss+ clients. High Seas clients add 2 extra bytes.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "Stygian Abyss", + "name": "SA Format", + "condition": "Client version 7.0.0.0 - 7.0.8.x (StygianAbyss, pre-HighSeas)", + "size": 24, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF3", + "description": "Packet identifier" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Command (always 1)" + }, + { + "name": "Entity Type", + "type": "enum", + "size": 1, + "description": "Entity type", + "values": [ + { "value": "0", "name": "Item", "description": "World item" }, + { "value": "1", "name": "Mobile", "description": "Mobile/creature" }, + { "value": "2", "name": "Multi", "description": "Multi/structure" } + ] + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + }, + { + "name": "Graphic ID", + "type": "ushort", + "size": 2, + "description": "Graphic/Body ID (masked with 0x7FFF)" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Direction (mobiles) or 0" + }, + { + "name": "Amount Min", + "type": "short", + "size": 2, + "description": "Minimum amount (items) or 1" + }, + { + "name": "Amount Max", + "type": "short", + "size": 2, + "description": "Maximum amount (items) or 1" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate (masked with 0x7FFF)" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate (masked with 0x3FFF)" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Z coordinate" + }, + { + "name": "Light", + "type": "byte", + "size": 1, + "description": "Light level (items)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Hue/color" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Packet flags (hidden, blessed, etc.)" + } + ] + }, + { + "version": "High Seas+", + "name": "HS Format", + "condition": "Client version \u003e= 7.0.9.0 (HighSeas)", + "size": 26, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF3", + "description": "Packet identifier" + }, + { + "name": "Command", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Command (always 1)" + }, + { + "name": "Entity Type", + "type": "enum", + "size": 1, + "description": "Entity type", + "values": [ + { "value": "0", "name": "Item", "description": "World item" }, + { "value": "1", "name": "Mobile", "description": "Mobile/creature" }, + { "value": "2", "name": "Multi", "description": "Multi/structure" } + ] + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Entity serial" + }, + { + "name": "Graphic ID", + "type": "ushort", + "size": 2, + "description": "Graphic/Body ID (masked with 0xFFFF, supports higher IDs)" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Direction (mobiles) or 0" + }, + { + "name": "Amount Min", + "type": "short", + "size": 2, + "description": "Minimum amount (items) or 1" + }, + { + "name": "Amount Max", + "type": "short", + "size": 2, + "description": "Maximum amount (items) or 1" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate (masked with 0x7FFF)" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate (masked with 0x3FFF)" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Z coordinate" + }, + { + "name": "Light", + "type": "byte", + "size": 1, + "description": "Light level (items)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Hue/color" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Packet flags (hidden, blessed, etc.)" + }, + { + "name": "Unknown", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Unknown (always 0)" + } + ] + } + ], + "related": [ + { + "id": "0x1A", + "relationship": "variant", + "note": "Legacy World Item packet for pre-SA clients" + } + ], + "clientVersion": { + "min": "7.0.0.0", + "feature": "StygianAbyss" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs", + "line": 88 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/equipment.json b/docs/packets/outgoing/equipment.json new file mode 100644 index 000000000..64d32d143 --- /dev/null +++ b/docs/packets/outgoing/equipment.json @@ -0,0 +1,173 @@ +{ + "category": "Equipment", + "packets": [ + { + "id": "0x2E", + "name": "Equip Update", + "description": "Notifies client that an item has been equipped on a mobile.", + "direction": "outgoing", + "isDynamic": false, + "size": 15, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x2E", + "description": "Packet identifier" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the equipped item" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Layer", + "type": "ushort", + "size": 2, + "description": "Equipment layer" + }, + { + "name": "Mobile Serial", + "type": "uint", + "size": 4, + "description": "Serial of the mobile wearing the item" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Item hue (may be overridden by SolidHueOverride)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs", + "line": 86 + } + }, + { + "id": "0xBF", + "subId": "0x10", + "name": "Display Equipment Info", + "description": "Displays detailed equipment information including crafter name and magical properties.", + "direction": "outgoing", + "isDynamic": true, + "size": "17+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0010", + "description": "Display Equipment Info subcommand" + }, + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Serial of the item" + }, + { + "name": "Cliloc Number", + "type": "int", + "size": 4, + "description": "Base cliloc number for item name" + }, + { + "name": "Crafter Info", + "type": "conditional", + "description": "Crafter information (if present)", + "condition": "crafterName.Length \u003e 0", + "fields": [ + { + "name": "Crafted By", + "type": "int", + "size": 4, + "value": "-3", + "description": "Crafter marker" + }, + { + "name": "Crafter Name Length", + "type": "ushort", + "size": 2, + "description": "Length of crafter name" + }, + { + "name": "Crafter Name", + "type": "ascii", + "description": "Crafter name" + } + ] + }, + { + "name": "Unidentified", + "type": "conditional", + "description": "Unidentified marker", + "condition": "unidentified", + "fields": [ + { + "name": "Unidentified Marker", + "type": "int", + "size": 4, + "value": "-4", + "description": "Unidentified marker" + } + ] + }, + { + "name": "Attributes", + "type": "loop", + "description": "Equipment attributes", + "loop": { + "countField": "variable", + "fields": [ + { + "name": "Attribute Number", + "type": "int", + "size": 4, + "description": "Attribute cliloc number" + }, + { + "name": "Charges", + "type": "short", + "size": 2, + "description": "Charges (-1 if not applicable)" + } + ] + } + }, + { + "name": "Terminator", + "type": "int", + "size": 4, + "value": "-1", + "description": "End of attributes marker" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEquipmentPackets.cs", + "line": 37 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/gump.json b/docs/packets/outgoing/gump.json new file mode 100644 index 000000000..ba24dfebc --- /dev/null +++ b/docs/packets/outgoing/gump.json @@ -0,0 +1,1043 @@ +{ + "category": "Gump", + "packets": [ + { + "id": "0x8B", + "name": "Display Sign Gump", + "description": "Displays a sign gump with text to the client.", + "direction": "outgoing", + "isDynamic": true, + "size": "15+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x8B", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Sign serial" + }, + { + "name": "Gump ID", + "type": "short", + "size": 2, + "description": "Gump graphic ID" + }, + { + "name": "Unknown Length", + "type": "short", + "size": 2, + "description": "Length of unknown text + 1" + }, + { + "name": "Unknown", + "type": "ascii-t", + "description": "Unknown text" + }, + { + "name": "Caption Length", + "type": "short", + "size": 2, + "description": "Length of caption + 1" + }, + { + "name": "Caption", + "type": "ascii-t", + "description": "Caption text" + } + ], + "source": { + "file": "Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs", + "line": 58 + } + }, + { + "id": "0xBF", + "subId": "0x04", + "name": "Close Gump", + "description": "Instructs client to close a specific gump.", + "direction": "outgoing", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "13", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0004", + "description": "Close Gump subcommand" + }, + { + "name": "Gump Type ID", + "type": "int", + "size": 4, + "description": "Gump type ID to close" + }, + { + "name": "Button ID", + "type": "int", + "size": 4, + "description": "Button ID (0 to close without response)" + } + ], + "source": { + "file": "Projects/UOContent/Gumps/Base/OutgoingGumpPackets.cs", + "line": 83 + } + }, + { + "id": "0xDD", + "name": "Dynamic Gump (Compressed)", + "description": "Sends a custom gump dialog with compressed layout and text strings. Uses raw DEFLATE compression (no zlib headers).", + "direction": "outgoing", + "isDynamic": true, + "size": "23+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDD", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Gump serial (unique per gump instance)" + }, + { + "name": "Type ID", + "type": "uint", + "size": 4, + "description": "Gump type ID (identifies the gump class)" + }, + { + "name": "X", + "type": "int", + "size": 4, + "description": "Screen X position" + }, + { + "name": "Y", + "type": "int", + "size": 4, + "description": "Screen Y position" + }, + { + "name": "Layout Compressed Length", + "type": "int", + "size": 4, + "description": "Compressed layout data length (includes +4)" + }, + { + "name": "Layout Uncompressed Length", + "type": "int", + "size": 4, + "description": "Uncompressed layout data length" + }, + { + "name": "Layout Data", + "type": "bytes", + "size": "var", + "description": "DEFLATE compressed layout commands (ASCII, no zlib header/footer). Length = Layout Compressed Length - 4" + }, + { + "name": "String Count", + "type": "int", + "size": 4, + "description": "Number of text strings" + }, + { + "name": "Strings Compressed Length", + "type": "int", + "size": 4, + "description": "Compressed strings data length (includes +4)" + }, + { + "name": "Strings Uncompressed Length", + "type": "int", + "size": 4, + "description": "Uncompressed strings data length" + }, + { + "name": "Strings Data", + "type": "bytes", + "size": "var", + "description": "DEFLATE compressed strings (no zlib header/footer). Length = Strings Compressed Length - 4" + } + ], + "compression": { + "algorithm": "DEFLATE (raw)", + "notes": "Uses libdeflate. NO zlib header (0x78 0x9C) or footer (adler32 checksum). Layout and strings are compressed separately." + }, + "layoutFormat": { + "description": "Layout is a custom ASCII text format. Each command is brace-wrapped: { command param1 param2 ... }", + "encoding": "ASCII (arguments must be ASCII characters only)", + "commands": [ + { + "name": "Noclose", + "description": "Prevent closing via right-click or ESC" + }, + { + "name": "Nomove", + "description": "Prevent dragging the gump" + }, + { + "name": "Noresize", + "description": "Prevent resizing (Enhanced Client)" + }, + { + "name": "Nodispose", + "description": "Prevent server-side disposal" + }, + { + "name": "Page", + "description": "Define page (0=base visible on all pages)", + "args": [ + { + "name": "N", + "type": "int", + "description": "Page number (0 = always visible)" + } + ] + }, + { + "name": "Group", + "description": "Radio button group ID", + "args": [ + { + "name": "Group ID", + "type": "int", + "description": "Group identifier for radio buttons" + } + ] + }, + { + "name": "Resizepic", + "description": "Resizable background panel (9-slice)", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Gump ID", + "type": "int", + "description": "Gump graphic ID for the background" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + } + ] + }, + { + "name": "Gumppic", + "description": "Static gump image", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Gump ID", + "type": "int", + "description": "Gump graphic ID" + }, + { + "name": "Hue=N", + "type": "int", + "description": "Optional hue override", + "optional": true + }, + { + "name": "Class=S", + "type": "string", + "description": "Optional CSS class (Enhanced Client)", + "optional": true + } + ] + }, + { + "name": "Gumppictiled", + "description": "Tiled gump image", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "Gump ID", + "type": "int", + "description": "Gump graphic ID to tile" + } + ] + }, + { + "name": "Tilepic", + "description": "Item/tile graphic from art.mul", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Item ID", + "type": "int", + "description": "Item graphic ID from art.mul" + } + ] + }, + { + "name": "Tilepichue", + "description": "Item graphic with hue", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Item ID", + "type": "int", + "description": "Item graphic ID" + }, + { + "name": "Hue", + "type": "int", + "description": "Color hue" + } + ] + }, + { + "name": "Picinpic", + "description": "Cropped sprite from gump", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Gump ID", + "type": "int", + "description": "Gump graphic ID" + }, + { + "name": "W", + "type": "int", + "description": "Display width" + }, + { + "name": "H", + "type": "int", + "description": "Display height" + }, + { + "name": "Sprite X", + "type": "int", + "description": "X offset within sprite" + }, + { + "name": "Sprite Y", + "type": "int", + "description": "Y offset within sprite" + } + ] + }, + { + "name": "Checkertrans", + "description": "Checkerboard transparency region", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + } + ] + }, + { + "name": "Text", + "description": "Static text label", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Hue", + "type": "int", + "description": "Text color hue" + }, + { + "name": "String Index", + "type": "int", + "description": "Index into strings array" + } + ] + }, + { + "name": "Croppedtext", + "description": "Cropped/clipped text", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Crop width" + }, + { + "name": "H", + "type": "int", + "description": "Crop height" + }, + { + "name": "Hue", + "type": "int", + "description": "Text color hue" + }, + { + "name": "String Index", + "type": "int", + "description": "Index into strings array" + } + ] + }, + { + "name": "Htmlgump", + "description": "HTML text area", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "String Index", + "type": "int", + "description": "Index into strings array (HTML content)" + }, + { + "name": "BG", + "type": "bool", + "description": "Display background panel" + }, + { + "name": "Scroll", + "type": "bool", + "description": "Display scrollbar" + } + ] + }, + { + "name": "Xmfhtmlgump", + "description": "Localized HTML from cliloc", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "Cliloc", + "type": "int", + "description": "Cliloc string number" + }, + { + "name": "BG", + "type": "bool", + "description": "Display background panel" + }, + { + "name": "Scroll", + "type": "bool", + "description": "Display scrollbar" + } + ] + }, + { + "name": "Xmfhtmlgumpcolor", + "description": "Localized HTML with color", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "Cliloc", + "type": "int", + "description": "Cliloc string number" + }, + { + "name": "BG", + "type": "bool", + "description": "Display background panel" + }, + { + "name": "Scroll", + "type": "bool", + "description": "Display scrollbar" + }, + { + "name": "Color", + "type": "int", + "description": "Text color (RGB format)" + } + ] + }, + { + "name": "Xmfhtmltok", + "description": "Localized HTML with arguments", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "BG", + "type": "bool", + "description": "Display background panel" + }, + { + "name": "Scroll", + "type": "bool", + "description": "Display scrollbar" + }, + { + "name": "Color", + "type": "int", + "description": "Text color (RGB format)" + }, + { + "name": "Cliloc", + "type": "int", + "description": "Cliloc string number" + }, + { + "name": "@Args@", + "type": "string", + "description": "Tab-separated cliloc arguments" + } + ] + }, + { + "name": "Button", + "description": "Clickable button", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Normal ID", + "type": "int", + "description": "Gump ID for normal state" + }, + { + "name": "Pressed ID", + "type": "int", + "description": "Gump ID for pressed state" + }, + { + "name": "Type", + "type": "enum", + "description": "Button type", + "values": [ + { "value": "0", "name": "PageChange", "description": "Navigate to different page" }, + { "value": "1", "name": "ServerReply", "description": "Send response to server" } + ] + }, + { + "name": "Param", + "type": "int", + "description": "Page number (Type=0) or unused (Type=1)" + }, + { + "name": "Button ID", + "type": "int", + "description": "Button ID sent to server on click" + } + ] + }, + { + "name": "Buttontileart", + "description": "Button with item overlay", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Normal ID", + "type": "int", + "description": "Gump ID for normal state" + }, + { + "name": "Pressed ID", + "type": "int", + "description": "Gump ID for pressed state" + }, + { + "name": "Type", + "type": "enum", + "description": "Button type", + "values": [ + { "value": "0", "name": "PageChange", "description": "Navigate to different page" }, + { "value": "1", "name": "ServerReply", "description": "Send response to server" } + ] + }, + { + "name": "Param", + "type": "int", + "description": "Page number (Type=0) or unused (Type=1)" + }, + { + "name": "Button ID", + "type": "int", + "description": "Button ID sent to server on click" + }, + { + "name": "Item ID", + "type": "int", + "description": "Item graphic ID to overlay" + }, + { + "name": "Hue", + "type": "int", + "description": "Item hue" + }, + { + "name": "W", + "type": "int", + "description": "Item display width" + }, + { + "name": "H", + "type": "int", + "description": "Item display height" + } + ] + }, + { + "name": "Checkbox", + "description": "Checkbox toggle", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Inactive ID", + "type": "int", + "description": "Gump ID when unchecked" + }, + { + "name": "Active ID", + "type": "int", + "description": "Gump ID when checked" + }, + { + "name": "State", + "type": "bool", + "description": "Initial checked state" + }, + { + "name": "Switch ID", + "type": "int", + "description": "Switch ID sent to server" + } + ] + }, + { + "name": "Radio", + "description": "Radio button (use with group)", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "Inactive ID", + "type": "int", + "description": "Gump ID when unselected" + }, + { + "name": "Active ID", + "type": "int", + "description": "Gump ID when selected" + }, + { + "name": "State", + "type": "bool", + "description": "Initial selected state" + }, + { + "name": "Switch ID", + "type": "int", + "description": "Switch ID sent to server" + } + ] + }, + { + "name": "Textentry", + "description": "Text input field", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "Hue", + "type": "int", + "description": "Text color hue" + }, + { + "name": "Entry ID", + "type": "int", + "description": "Entry ID for server response" + }, + { + "name": "String Index", + "type": "int", + "description": "Index into strings array (default text)" + } + ] + }, + { + "name": "Textentrylimited", + "description": "Text input with max length", + "args": [ + { + "name": "X", + "type": "int", + "description": "X coordinate" + }, + { + "name": "Y", + "type": "int", + "description": "Y coordinate" + }, + { + "name": "W", + "type": "int", + "description": "Width in pixels" + }, + { + "name": "H", + "type": "int", + "description": "Height in pixels" + }, + { + "name": "Hue", + "type": "int", + "description": "Text color hue" + }, + { + "name": "Entry ID", + "type": "int", + "description": "Entry ID for server response" + }, + { + "name": "String Index", + "type": "int", + "description": "Index into strings array (default text)" + }, + { + "name": "Max Len", + "type": "int", + "description": "Maximum character length" + } + ] + }, + { + "name": "Tooltip", + "description": "Tooltip on previous element", + "args": [ + { + "name": "Cliloc", + "type": "int", + "description": "Cliloc string number for tooltip" + }, + { + "name": "@Args@", + "type": "string", + "description": "Optional cliloc arguments", + "optional": true + } + ] + }, + { + "name": "Itemproperty", + "description": "Display item\u0027s OPL tooltip", + "args": [ + { + "name": "Serial", + "type": "int", + "description": "Item serial number" + } + ] + }, + { + "name": "Mastergump", + "description": "Master gump ID override", + "args": [ + { + "name": "Gump ID", + "type": "int", + "description": "Master gump identifier" + } + ] + } + ] + }, + "stringsFormat": { + "description": "Array of UTF-16 BE encoded strings for text/textentry elements", + "encoding": "UTF-16 Big Endian", + "entryFormat": [ + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "String length in characters (Big Endian)" + }, + { + "name": "Text", + "type": "utf16be", + "size": "var", + "description": "UTF-16 BE encoded text. Length = Length field * 2 bytes" + } + ] + }, + "related": [ + { + "id": "0xB1", + "relationship": "response", + "note": "Gump Response - client reply to button/checkbox/text" + } + ], + "clientVersion": { + "min": "3.0.0", + "feature": "Compressed gumps" + }, + "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": { + "file": "Projects/UOContent/Gumps/Base/DynamicGump.cs", + "line": 105 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/house.json b/docs/packets/outgoing/house.json new file mode 100644 index 000000000..071e7fbe8 --- /dev/null +++ b/docs/packets/outgoing/house.json @@ -0,0 +1,306 @@ +{ + "category": "House", + "packets": [ + { + "id": "0xD8", + "name": "House Design State Detailed", + "description": "Sends detailed house customization design data. Contains compressed plane data organized by floor level and component type. Tiles are encoded using grid-based or coordinate-based formats depending on their Z-height.", + "direction": "outgoing", + "isDynamic": true, + "size": "18+", + "tags": ["House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD8", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Compression Type", + "type": "byte", + "size": 1, + "value": "0x03", + "description": "Compression type (always 3 = compressed)" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown (always 0)" + }, + { + "name": "House Serial", + "type": "uint", + "size": 4, + "description": "Serial of the house foundation" + }, + { + "name": "Revision", + "type": "int", + "size": 4, + "description": "Design revision number" + }, + { + "name": "Tile Count", + "type": "ushort", + "size": 2, + "description": "Total number of tiles in the design" + }, + { + "name": "Buffer Length", + "type": "ushort", + "size": 2, + "description": "Length of remaining data (plane count + all plane sections)" + }, + { + "name": "Plane Count", + "type": "byte", + "size": 1, + "description": "Number of plane/buffer sections that follow" + }, + { + "name": "Plane Sections", + "type": "array", + "description": "Each section has a 4-byte header followed by compressed tile data", + "loop": { + "countField": "Plane Count", + "fields": [ + { + "name": "Section Header", + "type": "uint", + "size": 4, + "description": "Packed header: bits 28-31=mode, bits 24-27=planeZ, bits 16-23+(bits 4-7<<8)=decompLen, bits 8-15+(bits 0-3<<8)=compLen" + }, + { + "name": "Compressed Data", + "type": "bytes", + "size": "var", + "description": "DEFLATE compressed tile data (length from header)" + } + ] + } + } + ], + "planeFormat": { + "description": "Tiles are organized into planes based on Z-height. Planes 0-8 use grid encoding; planes 9+ use explicit coordinates for overflow items.", + "headerDecoding": { + "mode": "(header >> 28) & 0x0F", + "planeZ": "(header >> 24) & 0x0F", + "decompLen": "((header & 0xFF0000) >> 16) | ((header & 0xF0) << 4)", + "compLen": "((header & 0xFF00) >> 8) | ((header & 0x0F) << 8)" + }, + "planeZMapping": [ + { "plane": 0, "z": 0, "description": "Ground floor" }, + { "plane": 1, "z": 7, "description": "1st storey (floor items)" }, + { "plane": 2, "z": 27, "description": "2nd storey (floor items)" }, + { "plane": 3, "z": 47, "description": "3rd storey (floor items)" }, + { "plane": 4, "z": 67, "description": "4th storey (floor items)" }, + { "plane": "5-8", "z": "7/27/47/67", "description": "Non-floor items per storey" }, + { "plane": "9+", "z": "varies", "description": "Overflow/stair buffers (explicit coords)" } + ], + "encodingModes": [ + { + "mode": 0, + "name": "Full Coordinates", + "bytesPerTile": 5, + "format": "ushort itemId, sbyte x, sbyte y, sbyte z", + "description": "Used for overflow buffers with non-standard Z heights" + }, + { + "mode": 1, + "name": "XY Coordinates", + "bytesPerTile": 4, + "format": "ushort itemId, sbyte x, sbyte y", + "description": "Z calculated: ((planeZ - 1) % 4) * 20 + 7" + }, + { + "mode": 2, + "name": "Grid-Based", + "bytesPerTile": 2, + "format": "ushort itemId (0x0000 = empty)", + "description": "X,Y from grid index: x = i / gridHeight, y = i % gridHeight" + } + ], + "gridSizes": [ + { "plane": 0, "width": "width", "height": "height", "notes": "Full foundation footprint" }, + { "plane": "1-4", "width": "width - 1", "height": "height - 2", "notes": "Interior (floor items), offset by (1,1)" }, + { "plane": "5-8", "width": "width", "height": "height - 1", "notes": "Interior (non-floor items)" } + ] + }, + "compression": { + "algorithm": "DEFLATE", + "notes": "Raw DEFLATE compression (no zlib header/footer). Each plane buffer compressed independently. Max 750 items per overflow buffer (splits into multiple buffers if exceeded)." + }, + "related": [ + { + "id": "0xBF/0x1D", + "relationship": "related", + "note": "Design State General provides revision info only" + }, + { + "id": "0xBF/0x20", + "relationship": "related", + "note": "Begin/End House Customization commands" + } + ], + "clientVersion": { + "min": "4.0.0a", + "feature": "AOS House Customization" + }, + "source": { + "file": "Projects/UOContent/Multis/Houses/HousePackets.cs", + "line": 93 + } + }, + { + "id": "0xBF", + "subId": "0x1D", + "name": "Design State General", + "description": "Sends house design revision information. Client requests full details if revision differs.", + "direction": "outgoing", + "isDynamic": false, + "size": 13, + "tags": ["Extended Commands (0xBF)", "House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x000D", + "description": "Packet length (13)" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x001D", + "description": "Design State General subcommand" + }, + { + "name": "House Serial", + "type": "uint", + "size": 4, + "description": "Serial of the house" + }, + { + "name": "Revision", + "type": "int", + "size": 4, + "description": "Design revision number" + } + ], + "related": [ + { + "id": "0xD8", + "relationship": "related", + "note": "Full design details requested if revision differs" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HousePackets.cs", + "line": 72 + } + }, + { + "id": "0xBF", + "subId": "0x20", + "name": "Begin House Customization", + "description": "Notifies client to enter house customization mode.", + "direction": "outgoing", + "isDynamic": false, + "size": 17, + "tags": ["Extended Commands (0xBF)", "House"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0011", + "description": "Packet length (17)" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0020", + "description": "House Customization subcommand" + }, + { + "name": "House Serial", + "type": "uint", + "size": 4, + "description": "Serial of the house" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x04", + "description": "Begin customization command" + }, + { + "name": "Unknown 1", + "type": "ushort", + "size": 2, + "value": "0x0000", + "description": "Unknown (always 0)" + }, + { + "name": "Unknown 2", + "type": "ushort", + "size": 2, + "value": "0xFFFF", + "description": "Unknown (always 0xFFFF)" + }, + { + "name": "Unknown 3", + "type": "ushort", + "size": 2, + "value": "0xFFFF", + "description": "Unknown (always 0xFFFF)" + }, + { + "name": "Unknown 4", + "type": "byte", + "size": 1, + "value": "0xFF", + "description": "Unknown (always 0xFF)" + } + ], + "related": [ + { + "id": "0xBF/0x20", + "relationship": "variant", + "note": "End House Customization uses command 0x05" + } + ], + "source": { + "file": "Projects/UOContent/Multis/Houses/HousePackets.cs", + "line": 30 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/items.json b/docs/packets/outgoing/items.json new file mode 100644 index 000000000..133f98a07 --- /dev/null +++ b/docs/packets/outgoing/items.json @@ -0,0 +1,102 @@ +{ + "category": "Items", + "packets": [ + { + "id": "0x1A", + "name": "World Item", + "description": "Displays an item in the world (pre-Stygian Abyss clients).", + "direction": "outgoing", + "isDynamic": true, + "size": "14+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x1A", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length (14-20)" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Item serial (bit 31 set if amount present)" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID (bit 14 set for multi)" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Stack amount (if serial bit 31 set)", + "condition": "serial \u0026 0x80000000" + }, + { + "name": "X", + "type": "ushort", + "size": 2, + "description": "X coordinate (bit 15 set if direction present)" + }, + { + "name": "Y", + "type": "ushort", + "size": 2, + "description": "Y coordinate (bit 15=hue, bit 14=flags)" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Direction (if x bit 15 set)", + "condition": "x \u0026 0x8000" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Z coordinate" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue (if y bit 15 set)", + "condition": "y \u0026 0x8000" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Packet flags (if y bit 14 set)", + "condition": "y \u0026 0x4000" + } + ], + "related": [ + { + "id": "0xF3", + "relationship": "variant", + "note": "World Entity packet for SA+ clients" + } + ], + "notes": "For Stygian Abyss+ clients, use 0xF3 World Entity instead.", + "clientVersion": { + "max": "6.0.14.2", + "notes": "Replaced by 0xF3 for SA+ clients" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingItemPackets.cs", + "line": 24 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/light.json b/docs/packets/outgoing/light.json new file mode 100644 index 000000000..ea318024b --- /dev/null +++ b/docs/packets/outgoing/light.json @@ -0,0 +1,65 @@ +{ + "category": "Light", + "packets": [ + { + "id": "0x4E", + "name": "Personal Light Level", + "description": "Sets the light level for a specific entity.", + "direction": "outgoing", + "isDynamic": false, + "size": 6, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x4E", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity" + }, + { + "name": "Level", + "type": "byte", + "size": 1, + "description": "Light level (0=brightest, 25-30=typical night)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingLightPackets.cs", + "line": 23 + } + }, + { + "id": "0x4F", + "name": "Global Light Level", + "description": "Sets the global ambient light level for the client.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x4F", + "description": "Packet identifier" + }, + { + "name": "Level", + "type": "byte", + "size": 1, + "description": "Light level (0=brightest, 25-30=typical night)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingLightPackets.cs", + "line": 39 + } + } + ] +} diff --git a/docs/packets/outgoing/mahjong.json b/docs/packets/outgoing/mahjong.json new file mode 100644 index 000000000..e3de6cb1f --- /dev/null +++ b/docs/packets/outgoing/mahjong.json @@ -0,0 +1,501 @@ +{ + "category": "Mahjong", + "packets": [ + { + "id": "0xDA", + "subId": "0x19", + "name": "Mahjong Join Game", + "description": "Notifies client to open the Mahjong game interface.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0009", + "description": "Packet length (9)" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x0019", + "description": "Join Game command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 288 + } + }, + { + "id": "0xDA", + "subId": "0x03", + "name": "Mahjong Tile Info", + "description": "Sends information about a single Mahjong tile.", + "direction": "outgoing", + "isDynamic": false, + "size": 18, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0012", + "description": "Packet length (18)" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x0003", + "description": "Tile Info command" + }, + { + "name": "Tile Number", + "type": "byte", + "size": 1, + "description": "Tile index number" + }, + { + "name": "Tile Value", + "type": "byte", + "size": 1, + "description": "Tile face value (0 if hidden)" + }, + { + "name": "Y Position", + "type": "short", + "size": 2, + "description": "Tile Y coordinate" + }, + { + "name": "X Position", + "type": "short", + "size": 2, + "description": "Tile X coordinate" + }, + { + "name": "Stack Level", + "type": "byte", + "size": 1, + "description": "Stack level for overlapping tiles" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Tile direction (0=Up, 1=Left, 2=Down, 3=Right)" + }, + { + "name": "Flipped", + "type": "byte", + "size": 1, + "description": "0x10 if flipped/face-up, 0x00 if face-down" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 362 + } + }, + { + "id": "0xDA", + "subId": "0x04", + "name": "Mahjong Tiles Info", + "description": "Sends information about all tiles in the Mahjong game.", + "direction": "outgoing", + "isDynamic": true, + "size": "11+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x0004", + "description": "Tiles Info command" + }, + { + "name": "Tile Count", + "type": "short", + "size": 2, + "description": "Number of tiles" + }, + { + "name": "Tiles", + "type": "loop", + "description": "Tile data for each tile", + "loop": { + "countField": "Tile Count", + "fields": [ + { + "name": "Tile Number", + "type": "byte", + "size": 1, + "description": "Tile index number" + }, + { + "name": "Tile Value", + "type": "byte", + "size": 1, + "description": "Tile face value (0 if hidden)" + }, + { + "name": "Y Position", + "type": "short", + "size": 2, + "description": "Tile Y coordinate" + }, + { + "name": "X Position", + "type": "short", + "size": 2, + "description": "Tile X coordinate" + }, + { + "name": "Stack Level", + "type": "byte", + "size": 1, + "description": "Stack level" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Tile direction" + }, + { + "name": "Flipped", + "type": "byte", + "size": 1, + "description": "0x10 if flipped, 0x00 otherwise" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 408 + } + }, + { + "id": "0xDA", + "subId": "0x02", + "name": "Mahjong Players Info", + "description": "Sends information about all players in the Mahjong game.", + "direction": "outgoing", + "isDynamic": true, + "size": "11+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x0002", + "description": "Players Info command" + }, + { + "name": "Seat Count", + "type": "ushort", + "size": 2, + "description": "Number of seats with data" + }, + { + "name": "Players", + "type": "loop", + "description": "Player data for each seat", + "loop": { + "countField": "Seat Count", + "fields": [ + { + "name": "Player Serial", + "type": "uint", + "size": 4, + "description": "Serial of player (0 if empty)" + }, + { + "name": "Dealer Flag", + "type": "byte", + "size": 1, + "description": "1=Dealer, 2=Not dealer" + }, + { + "name": "Position", + "type": "byte", + "size": 1, + "description": "Seat position index" + }, + { + "name": "Score", + "type": "int", + "size": 4, + "description": "Player\u0027s current score" + }, + { + "name": "Reserved", + "type": "short", + "size": 2, + "value": "0", + "description": "Reserved (always 0)" + }, + { + "name": "Reserved 2", + "type": "byte", + "size": 1, + "value": "0", + "description": "Reserved (always 0)" + }, + { + "name": "Public Hand", + "type": "bool", + "size": 1, + "description": "True if hand is visible to others" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Player name" + }, + { + "name": "Empty Seat", + "type": "bool", + "size": 1, + "description": "True if seat is empty or not in game" + } + ] + } + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 304 + } + }, + { + "id": "0xDA", + "subId": "0x05", + "name": "Mahjong General Info", + "description": "Sends general game state including dice values, dealer indicator, and wall break position.", + "direction": "outgoing", + "isDynamic": false, + "size": 25, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0019", + "description": "Packet length (25)" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x0005", + "description": "General Info command" + }, + { + "name": "Reserved", + "type": "short", + "size": 2, + "value": "0", + "description": "Reserved" + }, + { + "name": "Reserved 2", + "type": "byte", + "size": 1, + "value": "0", + "description": "Reserved" + }, + { + "name": "Options", + "type": "byte", + "size": 1, + "description": "Bit 0: Show Scores, Bit 1: Spectator Vision" + }, + { + "name": "Dice 1", + "type": "byte", + "size": 1, + "description": "First dice value" + }, + { + "name": "Dice 2", + "type": "byte", + "size": 1, + "description": "Second dice value" + }, + { + "name": "Dealer Wind", + "type": "enum", + "size": 1, + "description": "Dealer indicator wind direction", + "values": [ + { "value": "0", "name": "North", "description": "North wind" }, + { "value": "1", "name": "East", "description": "East wind" }, + { "value": "2", "name": "South", "description": "South wind" }, + { "value": "3", "name": "West", "description": "West wind" } + ] + }, + { + "name": "Dealer Y", + "type": "short", + "size": 2, + "description": "Dealer indicator Y position" + }, + { + "name": "Dealer X", + "type": "short", + "size": 2, + "description": "Dealer indicator X position" + }, + { + "name": "Dealer Direction", + "type": "byte", + "size": 1, + "description": "Dealer indicator direction" + }, + { + "name": "Wall Break Y", + "type": "short", + "size": 2, + "description": "Wall break indicator Y position" + }, + { + "name": "Wall Break X", + "type": "short", + "size": 2, + "description": "Wall break indicator X position" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 461 + } + }, + { + "id": "0xDA", + "subId": "0x1A", + "name": "Mahjong Relieve", + "description": "Notifies client to close the Mahjong game interface.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xDA", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0009", + "description": "Packet length (9)" + }, + { + "name": "Game Serial", + "type": "uint", + "size": 4, + "description": "Serial of the Mahjong game" + }, + { + "name": "Command", + "type": "ushort", + "size": 2, + "value": "0x001A", + "description": "Relieve command" + } + ], + "source": { + "file": "Projects/UOContent/Items/Games/Mahjong/MahjongPackets.cs", + "line": 504 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/map.json b/docs/packets/outgoing/map.json new file mode 100644 index 000000000..eff31a607 --- /dev/null +++ b/docs/packets/outgoing/map.json @@ -0,0 +1,424 @@ +{ + "category": "Map", + "packets": [ + { + "id": "0xC6", + "name": "Invalid Map", + "description": "Notifies client that the current map is invalid.", + "direction": "outgoing", + "isDynamic": false, + "size": 1, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC6", + "description": "Packet identifier" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMapPackets.cs", + "line": 53 + } + }, + { + "id": "0xBF", + "subId": "0x08", + "name": "Map Change", + "description": "Notifies client of a facet/map change.", + "direction": "outgoing", + "isDynamic": false, + "size": 6, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Packet length (6)" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0008", + "description": "Map Change subcommand" + }, + { + "name": "Map ID", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Map/Facet ID", + "values": [ + { + "value": 0, + "name": "Felucca", + "description": "Felucca facet" + }, + { + "value": 1, + "name": "Trammel", + "description": "Trammel facet" + }, + { + "value": 2, + "name": "Ilshenar", + "description": "Ilshenar facet" + }, + { + "value": 3, + "name": "Malas", + "description": "Malas facet" + }, + { + "value": 4, + "name": "Tokuno", + "description": "Tokuno Islands facet" + }, + { + "value": 5, + "name": "Ter Mur", + "description": "Ter Mur facet" + } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMapPackets.cs", + "line": 55 + } + }, + { + "id": "0xBF", + "subId": "0x18", + "name": "Map Patches", + "description": "Sends map patch information for static and land blocks.", + "direction": "outgoing", + "isDynamic": false, + "size": 41, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0029", + "description": "Packet length (41)" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0018", + "description": "Map Patches subcommand" + }, + { + "name": "Map Count", + "type": "int", + "size": 4, + "value": "4", + "description": "Number of maps (always 4)" + }, + { + "name": "Patches", + "type": "loop", + "description": "Patch counts for each map (Felucca, Trammel, Ilshenar, Malas)", + "loop": { + "countField": "4", + "fields": [ + { + "name": "Static Blocks", + "type": "int", + "size": 4, + "description": "Number of patched static blocks" + }, + { + "name": "Land Blocks", + "type": "int", + "size": 4, + "description": "Number of patched land blocks" + } + ] + } + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMapPackets.cs", + "line": 25 + } + }, + { + "id": "0x56", + "name": "Map Command", + "description": "Server sends map pin commands to update the client\u0027s map display.", + "direction": "outgoing", + "isDynamic": false, + "size": 11, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x56", + "description": "Packet identifier" + }, + { + "name": "Map Serial", + "type": "uint", + "size": 4, + "description": "Serial of the map item" + }, + { + "name": "Command", + "type": "enum", + "size": 1, + "description": "Map command type", + "values": [ + { "value": "1", "name": "AddPin", "description": "Add a pin to the map" }, + { "value": "5", "name": "DisplayMap", "description": "Display the map to client" }, + { "value": "7", "name": "SetEditable", "description": "Set map editable state" } + ] + }, + { + "name": "Editable", + "type": "bool", + "size": 1, + "description": "True if map is editable (for command 7)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate of pin" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate of pin" + } + ], + "related": [ + { + "id": "0x56", + "direction": "incoming", + "relationship": "related", + "note": "Client map pin commands" + }, + { + "id": "0x90", + "relationship": "related", + "note": "Map Details packet (old)" + }, + { + "id": "0xF5", + "relationship": "related", + "note": "Map Details packet (new)" + } + ], + "source": { + "file": "Projects/UOContent/Items/Maps/MapItemPackets.cs", + "line": 106 + } + }, + { + "id": "0x90", + "name": "Map Details", + "description": "Sends map details including bounds, dimensions, and graphic ID. Pre-NewCharacterList clients.", + "direction": "outgoing", + "isDynamic": false, + "size": 19, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x90", + "description": "Packet identifier" + }, + { + "name": "Map Serial", + "type": "uint", + "size": 4, + "description": "Serial of the map item" + }, + { + "name": "Graphic ID", + "type": "short", + "size": 2, + "value": "0x139D", + "description": "Map gump graphic ID" + }, + { + "name": "Start X", + "type": "short", + "size": 2, + "description": "Map bounds start X coordinate" + }, + { + "name": "Start Y", + "type": "short", + "size": 2, + "description": "Map bounds start Y coordinate" + }, + { + "name": "End X", + "type": "short", + "size": 2, + "description": "Map bounds end X coordinate" + }, + { + "name": "End Y", + "type": "short", + "size": 2, + "description": "Map bounds end Y coordinate" + }, + { + "name": "Width", + "type": "short", + "size": 2, + "description": "Map width in pixels" + }, + { + "name": "Height", + "type": "short", + "size": 2, + "description": "Map height in pixels" + } + ], + "related": [ + { + "id": "0x56", + "direction": "both", + "relationship": "related", + "note": "Map pin commands (client and server)" + }, + { + "id": "0xF5", + "relationship": "variant", + "note": "New Map Details for NewCharacterList clients" + } + ], + "source": { + "file": "Projects/UOContent/Items/Maps/MapItemPackets.cs", + "line": 78 + } + }, + { + "id": "0xF5", + "name": "Map Details (New)", + "description": "Sends map details for NewCharacterList clients. Includes facet ID.", + "direction": "outgoing", + "isDynamic": false, + "size": 21, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF5", + "description": "Packet identifier" + }, + { + "name": "Map Serial", + "type": "uint", + "size": 4, + "description": "Serial of the map item" + }, + { + "name": "Graphic ID", + "type": "short", + "size": 2, + "value": "0x139D", + "description": "Map gump graphic ID" + }, + { + "name": "Start X", + "type": "short", + "size": 2, + "description": "Map bounds start X coordinate" + }, + { + "name": "Start Y", + "type": "short", + "size": 2, + "description": "Map bounds start Y coordinate" + }, + { + "name": "End X", + "type": "short", + "size": 2, + "description": "Map bounds end X coordinate" + }, + { + "name": "End Y", + "type": "short", + "size": 2, + "description": "Map bounds end Y coordinate" + }, + { + "name": "Width", + "type": "short", + "size": 2, + "description": "Map width in pixels" + }, + { + "name": "Height", + "type": "short", + "size": 2, + "description": "Map height in pixels" + }, + { + "name": "Facet ID", + "type": "enum", + "size": 2, + "description": "Map facet/world identifier", + "values": [ + { "value": "0", "name": "Felucca", "description": "Felucca facet" }, + { "value": "1", "name": "Trammel", "description": "Trammel facet" }, + { "value": "2", "name": "Ilshenar", "description": "Ilshenar facet" }, + { "value": "3", "name": "Malas", "description": "Malas facet" }, + { "value": "4", "name": "Tokuno", "description": "Tokuno Islands" }, + { "value": "5", "name": "TerMur", "description": "Ter Mur facet" } + ] + } + ], + "related": [ + { + "id": "0x56", + "direction": "both", + "relationship": "related", + "note": "Map pin commands (client and server)" + }, + { + "id": "0x90", + "relationship": "variant", + "note": "Old Map Details for pre-NewCharacterList clients" + } + ], + "clientVersion": { + "min": "7.0.13.0", + "feature": "NewCharacterList" + }, + "source": { + "file": "Projects/UOContent/Items/Maps/MapItemPackets.cs", + "line": 78 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/menu.json b/docs/packets/outgoing/menu.json new file mode 100644 index 000000000..57d330ce6 --- /dev/null +++ b/docs/packets/outgoing/menu.json @@ -0,0 +1,185 @@ +{ + "category": "Menu", + "packets": [ + { + "id": "0x7C", + "name": "Display Menu", + "description": "Displays an item list menu or question menu to the client.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Item List Menu", + "condition": "Menu is ItemListMenu", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x7C", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Menu Serial", + "type": "uint", + "size": 4, + "description": "Menu serial" + }, + { + "name": "Menu ID", + "type": "ushort", + "size": 2, + "value": "0x0000", + "description": "Menu ID (always 0)" + }, + { + "name": "Question Length", + "type": "byte", + "size": 1, + "description": "Length of question text" + }, + { + "name": "Question", + "type": "ascii", + "description": "Question text" + }, + { + "name": "Entry Count", + "type": "byte", + "size": 1, + "description": "Number of menu entries" + }, + { + "name": "Entries", + "type": "loop", + "description": "Menu entries", + "loop": { + "countField": "entryCount", + "fields": [ + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Item hue" + }, + { + "name": "Name Length", + "type": "byte", + "size": 1, + "description": "Length of entry name" + }, + { + "name": "Name", + "type": "ascii", + "description": "Entry name" + } + ] + } + } + ] + }, + { + "name": "Question Menu", + "condition": "Menu is QuestionMenu", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x7C", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Menu Serial", + "type": "uint", + "size": 4, + "description": "Menu serial" + }, + { + "name": "Menu ID", + "type": "ushort", + "size": 2, + "value": "0x0000", + "description": "Menu ID (always 0)" + }, + { + "name": "Question Length", + "type": "byte", + "size": 1, + "description": "Length of question text" + }, + { + "name": "Question", + "type": "ascii", + "description": "Question text" + }, + { + "name": "Answer Count", + "type": "byte", + "size": 1, + "description": "Number of answers" + }, + { + "name": "Answers", + "type": "loop", + "description": "Answer options", + "loop": { + "countField": "answerCount", + "fields": [ + { + "name": "Padding", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused padding" + }, + { + "name": "Answer Length", + "type": "byte", + "size": 1, + "description": "Length of answer text" + }, + { + "name": "Answer", + "type": "ascii", + "description": "Answer text" + } + ] + } + } + ] + } + ], + "related": [ + { + "id": "0x7D", + "relationship": "response", + "note": "Menu Response from client" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMenuPackets.cs", + "line": 36 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/message.json b/docs/packets/outgoing/message.json new file mode 100644 index 000000000..7369cbd50 --- /dev/null +++ b/docs/packets/outgoing/message.json @@ -0,0 +1,534 @@ +{ + "category": "Message", + "packets": [ + { + "id": "0x15", + "name": "Follow Message", + "description": "Instructs client to follow one entity with another.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x15", + "description": "Packet identifier" + }, + { + "name": "Follower Serial", + "type": "uint", + "size": 4, + "description": "Serial of the follower" + }, + { + "name": "Target Serial", + "type": "uint", + "size": 4, + "description": "Serial of the target to follow" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 231 + } + }, + { + "id": "0x1C", + "name": "ASCII Message", + "description": "Server sends ASCII-encoded message to client.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x1C", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of speaker (0xFFFFFFFF for system)" + }, + { + "name": "Graphic", + "type": "short", + "size": 2, + "description": "Body graphic of speaker" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Message type", + "values": [ + { + "value": 0, + "name": "Regular", + "description": "Normal speech" + }, + { + "value": 1, + "name": "System", + "description": "System message" + }, + { + "value": 2, + "name": "Emote", + "description": "Emote (*action*)" + }, + { + "value": 6, + "name": "Label", + "description": "Object label" + }, + { + "value": 7, + "name": "Focus", + "description": "Focused message" + }, + { + "value": 8, + "name": "Whisper", + "description": "Whisper" + }, + { + "value": 9, + "name": "Yell", + "description": "Yell" + }, + { + "value": 10, + "name": "Spell", + "description": "Spell words" + }, + { + "value": 13, + "name": "Guild", + "description": "Guild chat" + }, + { + "value": 14, + "name": "Alliance", + "description": "Alliance chat" + }, + { + "value": 15, + "name": "Command", + "description": "Command" + } + ] + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Speaker name" + }, + { + "name": "Text", + "type": "ascii-t", + "description": "Message text" + } + ], + "related": [ + { + "id": "0x03", + "relationship": "request", + "note": "ASCII Speech from client" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 180 + } + }, + { + "id": "0xAE", + "name": "Unicode Message", + "description": "Server sends Unicode-encoded message to client.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xAE", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of speaker (0xFFFFFFFF for system)" + }, + { + "name": "Graphic", + "type": "short", + "size": 2, + "description": "Body graphic of speaker" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Message type (see 0x1C)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Language", + "type": "ascii", + "size": 4, + "description": "Language code (e.g., \u0027ENU\u0027)" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Speaker name" + }, + { + "name": "Text", + "type": "utf16be-t", + "description": "Message text (Big Endian Unicode)" + } + ], + "related": [ + { + "id": "0xAD", + "relationship": "request", + "note": "Unicode Speech from client" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 180 + } + }, + { + "id": "0xB7", + "name": "Help Response", + "description": "Server sends help text response to client.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB7", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of entity" + }, + { + "name": "Text", + "type": "utf16be-t", + "description": "Help text" + } + ], + "related": [ + { + "id": "0xB6", + "relationship": "request", + "note": "Object Help Request from client" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 263 + } + }, + { + "id": "0xC1", + "name": "Localized Message", + "description": "Server sends a localized (cliloc) message to client.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC1", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of speaker" + }, + { + "name": "Graphic", + "type": "short", + "size": 2, + "description": "Body graphic of speaker" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Message type (see 0x1C)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Cliloc Number", + "type": "int", + "size": 4, + "description": "Cliloc entry number" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Speaker name" + }, + { + "name": "Arguments", + "type": "utf16le-t", + "description": "Tab-separated arguments for cliloc" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 55 + } + }, + { + "id": "0xC2", + "name": "Unicode Prompt", + "description": "Server requests text input from client.", + "direction": "outgoing", + "isDynamic": false, + "size": 21, + "tags": ["Menu"], + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC2", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "21", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Prompt serial" + }, + { + "name": "Prompt ID", + "type": "uint", + "size": 4, + "description": "Prompt ID (same as serial)" + }, + { + "name": "Padding", + "type": "byte[]", + "size": 10, + "description": "Unused padding (zeros)" + } + ], + "related": [ + { + "id": "0x9A", + "direction": "incoming", + "relationship": "response", + "note": "ASCII Prompt Response" + }, + { + "id": "0xC2", + "direction": "incoming", + "relationship": "response", + "note": "Unicode Prompt Response" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 246 + } + }, + { + "id": "0xCC", + "name": "Localized Message Affix", + "description": "Server sends a localized message with text prefix/suffix.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xCC", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of speaker" + }, + { + "name": "Graphic", + "type": "short", + "size": 2, + "description": "Body graphic of speaker" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Message type (see 0x1C)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Text color hue" + }, + { + "name": "Font", + "type": "short", + "size": 2, + "description": "Font ID" + }, + { + "name": "Cliloc Number", + "type": "int", + "size": 4, + "description": "Cliloc entry number" + }, + { + "name": "Affix Type", + "type": "enum", + "size": 1, + "description": "How to apply the affix", + "values": [ + { + "value": 0, + "name": "Append", + "description": "Append affix to end" + }, + { + "value": 1, + "name": "Prepend", + "description": "Prepend affix to start" + }, + { + "value": 2, + "name": "System", + "description": "System message style" + } + ] + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Speaker name" + }, + { + "name": "Affix", + "type": "ascii-t", + "description": "Text to prepend/append" + }, + { + "name": "Arguments", + "type": "utf16be-t", + "description": "Tab-separated arguments for cliloc" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 112 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/mobile.json b/docs/packets/outgoing/mobile.json new file mode 100644 index 000000000..6c49fcb99 --- /dev/null +++ b/docs/packets/outgoing/mobile.json @@ -0,0 +1,1757 @@ +{ + "category": "Mobile", + "packets": [ + { + "id": "0x11", + "name": "Mobile Status", + "description": "Detailed status information for a mobile. Version 0 (compact) is sent when viewing other mobiles. Versions 3-6 are sent for self based on expansion.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "version": "Version 0 (Compact)", + "name": "Other Mobile Status", + "condition": "Viewing another mobile (not self)", + "size": 43, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "43", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits (normalized 0-100)" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "value": "100", + "description": "Maximum hits (always 100 for normalized)" + }, + { + "name": "Can Be Renamed", + "type": "bool", + "size": 1, + "description": "Whether the mobile can be renamed by viewer" + }, + { + "name": "Version", + "type": "byte", + "size": 1, + "value": "0", + "description": "Status version (0 = compact)" + } + ] + }, + { + "version": "Version 3 (Basic)", + "name": "Self Status (Pre-AOS)", + "condition": "Viewing self, pre-AOS expansion", + "size": 70, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "70", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Can Be Renamed", + "type": "bool", + "size": 1, + "description": "Whether the mobile can be renamed" + }, + { + "name": "Version", + "type": "byte", + "size": 1, + "value": "3", + "description": "Status version" + }, + { + "name": "Female", + "type": "bool", + "size": 1, + "description": "Gender flag (true = female)" + }, + { + "name": "Str", + "type": "short", + "size": 2, + "description": "Strength" + }, + { + "name": "Dex", + "type": "short", + "size": 2, + "description": "Dexterity" + }, + { + "name": "Int", + "type": "short", + "size": 2, + "description": "Intelligence" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Total gold in backpack" + }, + { + "name": "Armor Rating", + "type": "short", + "size": 2, + "description": "Armor rating" + }, + { + "name": "Weight", + "type": "short", + "size": 2, + "description": "Current weight (body weight + carried)" + }, + { + "name": "Stat Cap", + "type": "short", + "size": 2, + "description": "Total stat cap" + }, + { + "name": "Followers", + "type": "byte", + "size": 1, + "description": "Current follower count" + }, + { + "name": "Followers Max", + "type": "byte", + "size": 1, + "description": "Maximum follower slots" + } + ] + }, + { + "version": "Version 4 (AOS)", + "name": "Self Status (Age of Shadows)", + "condition": "Viewing self, AOS expansion", + "size": 88, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "88", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Can Be Renamed", + "type": "bool", + "size": 1, + "description": "Whether the mobile can be renamed" + }, + { + "name": "Version", + "type": "byte", + "size": 1, + "value": "4", + "description": "Status version" + }, + { + "name": "Female", + "type": "bool", + "size": 1, + "description": "Gender flag (true = female)" + }, + { + "name": "Str", + "type": "short", + "size": 2, + "description": "Strength" + }, + { + "name": "Dex", + "type": "short", + "size": 2, + "description": "Dexterity" + }, + { + "name": "Int", + "type": "short", + "size": 2, + "description": "Intelligence" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Total gold in backpack" + }, + { + "name": "Physical Resist", + "type": "short", + "size": 2, + "description": "Physical resistance" + }, + { + "name": "Weight", + "type": "short", + "size": 2, + "description": "Current weight" + }, + { + "name": "Stat Cap", + "type": "short", + "size": 2, + "description": "Total stat cap" + }, + { + "name": "Followers", + "type": "byte", + "size": 1, + "description": "Current follower count" + }, + { + "name": "Followers Max", + "type": "byte", + "size": 1, + "description": "Maximum follower slots" + }, + { + "name": "Fire Resist", + "type": "short", + "size": 2, + "description": "Fire resistance" + }, + { + "name": "Cold Resist", + "type": "short", + "size": 2, + "description": "Cold resistance" + }, + { + "name": "Poison Resist", + "type": "short", + "size": 2, + "description": "Poison resistance" + }, + { + "name": "Energy Resist", + "type": "short", + "size": 2, + "description": "Energy resistance" + }, + { + "name": "Luck", + "type": "short", + "size": 2, + "description": "Luck" + }, + { + "name": "Damage Min", + "type": "short", + "size": 2, + "description": "Minimum weapon damage" + }, + { + "name": "Damage Max", + "type": "short", + "size": 2, + "description": "Maximum weapon damage" + }, + { + "name": "Tithing Points", + "type": "int", + "size": 4, + "description": "Tithing points (for Chivalry)" + } + ] + }, + { + "version": "Version 5 (ML)", + "name": "Self Status (Mondain\u0027s Legacy)", + "condition": "Viewing self, ML expansion", + "size": 91, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "91", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Can Be Renamed", + "type": "bool", + "size": 1, + "description": "Whether the mobile can be renamed" + }, + { + "name": "Version", + "type": "byte", + "size": 1, + "value": "5", + "description": "Status version" + }, + { + "name": "Female", + "type": "bool", + "size": 1, + "description": "Gender flag (true = female)" + }, + { + "name": "Str", + "type": "short", + "size": 2, + "description": "Strength" + }, + { + "name": "Dex", + "type": "short", + "size": 2, + "description": "Dexterity" + }, + { + "name": "Int", + "type": "short", + "size": 2, + "description": "Intelligence" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Total gold in backpack" + }, + { + "name": "Physical Resist", + "type": "short", + "size": 2, + "description": "Physical resistance" + }, + { + "name": "Weight", + "type": "short", + "size": 2, + "description": "Current weight" + }, + { + "name": "Max Weight", + "type": "short", + "size": 2, + "description": "Maximum carry weight" + }, + { + "name": "Race", + "type": "byte", + "size": 1, + "description": "Race ID + 1 (1=Human, 2=Elf, 0=none)" + }, + { + "name": "Stat Cap", + "type": "short", + "size": 2, + "description": "Total stat cap" + }, + { + "name": "Followers", + "type": "byte", + "size": 1, + "description": "Current follower count" + }, + { + "name": "Followers Max", + "type": "byte", + "size": 1, + "description": "Maximum follower slots" + }, + { + "name": "Fire Resist", + "type": "short", + "size": 2, + "description": "Fire resistance" + }, + { + "name": "Cold Resist", + "type": "short", + "size": 2, + "description": "Cold resistance" + }, + { + "name": "Poison Resist", + "type": "short", + "size": 2, + "description": "Poison resistance" + }, + { + "name": "Energy Resist", + "type": "short", + "size": 2, + "description": "Energy resistance" + }, + { + "name": "Luck", + "type": "short", + "size": 2, + "description": "Luck" + }, + { + "name": "Damage Min", + "type": "short", + "size": 2, + "description": "Minimum weapon damage" + }, + { + "name": "Damage Max", + "type": "short", + "size": 2, + "description": "Maximum weapon damage" + }, + { + "name": "Tithing Points", + "type": "int", + "size": 4, + "description": "Tithing points (for Chivalry)" + } + ] + }, + { + "version": "Version 6 (HS)", + "name": "Self Status (High Seas)", + "condition": "Viewing self, High Seas expansion with ExtendedStatus", + "size": 121, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x11", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "121", + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Can Be Renamed", + "type": "bool", + "size": 1, + "description": "Whether the mobile can be renamed" + }, + { + "name": "Version", + "type": "byte", + "size": 1, + "value": "6", + "description": "Status version" + }, + { + "name": "Female", + "type": "bool", + "size": 1, + "description": "Gender flag (true = female)" + }, + { + "name": "Str", + "type": "short", + "size": 2, + "description": "Strength" + }, + { + "name": "Dex", + "type": "short", + "size": 2, + "description": "Dexterity" + }, + { + "name": "Int", + "type": "short", + "size": 2, + "description": "Intelligence" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Total gold in backpack" + }, + { + "name": "Physical Resist", + "type": "short", + "size": 2, + "description": "Physical resistance" + }, + { + "name": "Weight", + "type": "short", + "size": 2, + "description": "Current weight" + }, + { + "name": "Max Weight", + "type": "short", + "size": 2, + "description": "Maximum carry weight" + }, + { + "name": "Race", + "type": "byte", + "size": 1, + "description": "Race ID + 1 (1=Human, 2=Elf, 3=Gargoyle)" + }, + { + "name": "Stat Cap", + "type": "short", + "size": 2, + "description": "Total stat cap" + }, + { + "name": "Followers", + "type": "byte", + "size": 1, + "description": "Current follower count" + }, + { + "name": "Followers Max", + "type": "byte", + "size": 1, + "description": "Maximum follower slots" + }, + { + "name": "Fire Resist", + "type": "short", + "size": 2, + "description": "Fire resistance" + }, + { + "name": "Cold Resist", + "type": "short", + "size": 2, + "description": "Cold resistance" + }, + { + "name": "Poison Resist", + "type": "short", + "size": 2, + "description": "Poison resistance" + }, + { + "name": "Energy Resist", + "type": "short", + "size": 2, + "description": "Energy resistance" + }, + { + "name": "Luck", + "type": "short", + "size": 2, + "description": "Luck" + }, + { + "name": "Damage Min", + "type": "short", + "size": 2, + "description": "Minimum weapon damage" + }, + { + "name": "Damage Max", + "type": "short", + "size": 2, + "description": "Maximum weapon damage" + }, + { + "name": "Tithing Points", + "type": "int", + "size": 4, + "description": "Tithing points (for Chivalry)" + }, + { + "name": "Aos Statuses", + "type": "short[15]", + "size": 30, + "description": "Extended AOS status values. Array of 15 shorts indexed by status type.", + "values": [ + { + "value": 0, + "name": "Max Physical Resist", + "description": "Maximum physical resistance cap" + }, + { + "value": 1, + "name": "Max Fire Resist", + "description": "Maximum fire resistance cap" + }, + { + "value": 2, + "name": "Max Cold Resist", + "description": "Maximum cold resistance cap" + }, + { + "value": 3, + "name": "Max Poison Resist", + "description": "Maximum poison resistance cap" + }, + { + "value": 4, + "name": "Max Energy Resist", + "description": "Maximum energy resistance cap" + }, + { + "value": 5, + "name": "Defense Chance Increase", + "description": "Current defense chance increase %" + }, + { + "value": 6, + "name": "Defense Chance Cap", + "description": "Maximum defense chance cap (always 45)" + }, + { + "value": 7, + "name": "Hit Chance Increase", + "description": "Hit chance increase %" + }, + { + "value": 8, + "name": "Swing Speed Increase", + "description": "Swing speed increase %" + }, + { + "value": 9, + "name": "Damage Increase", + "description": "Damage increase %" + }, + { + "value": 10, + "name": "Lower Reagent Cost", + "description": "Lower reagent cost %" + }, + { + "value": 11, + "name": "Spell Damage Increase", + "description": "Spell damage increase %" + }, + { + "value": 12, + "name": "Faster Cast Recovery", + "description": "Faster cast recovery" + }, + { + "value": 13, + "name": "Faster Casting", + "description": "Faster casting" + }, + { + "value": 14, + "name": "Lower Mana Cost", + "description": "Lower mana cost %" + } + ] + } + ], + "notes": "Enhanced Client supports additional status indices 15-28 (HP/Stam/Mana regen, Reflect Physical, Enhance Potions, Stat Increases). ModernUO does not support Enhanced Client." + } + ], + "notes": "ModernUO supports 15 AOS status values (indices 0-14). Enhanced Client extends this to 29 values (indices 0-28), but ModernUO does not support Enhanced Client.", + "related": [ + { + "id": "0x34", + "direction": "incoming", + "relationship": "request", + "note": "Mobile Query (stats) triggers this response" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 497 + } + }, + { + "id": "0x20", + "name": "Mobile Update", + "description": "Updates a mobile\u0027s basic display information (body, hue, position, flags).", + "direction": "outgoing", + "isDynamic": false, + "size": 19, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x20", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Body", + "type": "short", + "size": 2, + "description": "Body/graphic ID" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "description": "Unknown (always 0)" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Hue/color (or solid hue override)" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Packet flags (hidden, poisoned, etc.)" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Y coordinate" + }, + { + "name": "Unknown2", + "type": "short", + "size": 2, + "description": "Unknown (always 0)" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Facing direction" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Z coordinate" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 578 + } + }, + { + "id": "0x77", + "name": "Mobile Moving", + "description": "Sent when a mobile moves. Contains position, direction, hue, and notoriety.", + "direction": "outgoing", + "isDynamic": false, + "size": 17, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x77", + "description": "Packet identifier" + }, + { + "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": "Direction (0-7) with running flag (0x80)" + }, + { + "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" + } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 104 + } + }, + { + "id": "0x78", + "name": "Mobile Incoming", + "description": "Full mobile information including equipped items. Sent when a mobile enters view range.", + "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 (bit 0x8000 = hue follows for old clients)" + }, + { + "name": "Layer", + "type": "byte", + "size": 1, + "description": "Equipment layer" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Item hue (only if bit 0x8000 set or NewMobileIncoming)", + "condition": "hue flag or NewMobileIncoming" + } + ] + } + }, + { + "name": "Terminator", + "type": "int", + "size": 4, + "value": "0x00000000", + "description": "Equipment list terminator" + } + ], + "clientVersion": { + "feature": "NewMobileIncoming", + "notes": "NewMobileIncoming clients always include hue field for equipment" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 601 + } + }, + { + "id": "0xA1", + "name": "Mobile Hits", + "description": "Updates a mobile\u0027s hit points. Can be normalized to 0-100 scale for non-self mobiles.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA1", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 210 + } + }, + { + "id": "0xA2", + "name": "Mobile Mana", + "description": "Updates a mobile\u0027s mana points.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA2", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 235 + } + }, + { + "id": "0xA3", + "name": "Mobile Stamina", + "description": "Updates a mobile\u0027s stamina points.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA3", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 260 + } + }, + { + "id": "0x2D", + "name": "Mobile Attributes", + "description": "Updates all three attribute bars (hits, mana, stamina) in a single packet.", + "direction": "outgoing", + "isDynamic": false, + "size": 17, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x2D", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Hits Max", + "type": "short", + "size": 2, + "description": "Maximum hits" + }, + { + "name": "Hits", + "type": "short", + "size": 2, + "description": "Current hits" + }, + { + "name": "Mana Max", + "type": "short", + "size": 2, + "description": "Maximum mana" + }, + { + "name": "Mana", + "type": "short", + "size": 2, + "description": "Current mana" + }, + { + "name": "Stam Max", + "type": "short", + "size": 2, + "description": "Maximum stamina" + }, + { + "name": "Stam", + "type": "short", + "size": 2, + "description": "Current stamina" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 285 + } + }, + { + "id": "0x98", + "name": "Mobile Name", + "description": "Returns a mobile\u0027s name in response to a name request.", + "direction": "outgoing", + "isDynamic": false, + "size": 37, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x98", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0025", + "description": "Packet length (37)" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Name", + "type": "ascii", + "size": 30, + "description": "Mobile name (null-terminated)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 301 + } + }, + { + "id": "0x6E", + "name": "Mobile Animation", + "description": "Triggers an animation on a mobile.", + "direction": "outgoing", + "isDynamic": false, + "size": 14, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6E", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Action", + "type": "short", + "size": 2, + "description": "Animation action ID" + }, + { + "name": "Frame Count", + "type": "short", + "size": 2, + "description": "Number of frames" + }, + { + "name": "Repeat Count", + "type": "short", + "size": 2, + "description": "Number of times to repeat" + }, + { + "name": "Reverse", + "type": "bool", + "size": 1, + "description": "Play animation in reverse" + }, + { + "name": "Repeat", + "type": "bool", + "size": 1, + "description": "Loop the animation" + }, + { + "name": "Delay", + "type": "byte", + "size": 1, + "description": "Frame delay" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 318 + } + }, + { + "id": "0xE2", + "name": "New Mobile Animation", + "description": "Simplified animation packet for newer clients.", + "direction": "outgoing", + "isDynamic": false, + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xE2", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Action", + "type": "short", + "size": 2, + "description": "Animation action ID" + }, + { + "name": "Frame Count", + "type": "short", + "size": 2, + "description": "Number of frames" + }, + { + "name": "Delay", + "type": "byte", + "size": 1, + "description": "Frame delay" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 354 + } + }, + { + "id": "0x17", + "name": "Mobile Healthbar", + "description": "Updates a mobile\u0027s healthbar status (poison level, yellow bar for invulnerability).", + "direction": "outgoing", + "isDynamic": false, + "size": 12, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x17", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x000C", + "description": "Packet length (12)" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Mobile serial" + }, + { + "name": "Show Bar", + "type": "short", + "size": 2, + "value": "0x0001", + "description": "Show bar (always 1)" + }, + { + "name": "Healthbar Type", + "type": "enum", + "size": 2, + "description": "Type of healthbar overlay", + "values": [ + { "value": "1", "name": "Poison", "description": "Poison status bar" }, + { "value": "2", "name": "Yellow", "description": "Yellow/invulnerable bar" } + ] + }, + { + "name": "Level", + "type": "enum", + "size": 1, + "description": "Status level", + "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)" } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 419 + } + }, + { + "id": "0xAF", + "name": "Death Animation", + "description": "Triggers the death animation and corpse creation for a mobile.", + "direction": "outgoing", + "isDynamic": false, + "size": 13, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xAF", + "description": "Packet identifier" + }, + { + "name": "Killed Serial", + "type": "uint", + "size": 4, + "description": "Serial of the killed mobile" + }, + { + "name": "Corpse Serial", + "type": "uint", + "size": 4, + "description": "Serial of the corpse created" + }, + { + "name": "Unknown", + "type": "int", + "size": 4, + "description": "Unknown (always 0)" + } + ], + "source": { + "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 new file mode 100644 index 000000000..79153d476 --- /dev/null +++ b/docs/packets/outgoing/movement.json @@ -0,0 +1,256 @@ +{ + "category": "Movement", + "packets": [ + { + "id": "0x21", + "name": "Movement Rejection", + "description": "Sent by the server when player movement is blocked (collision, teleport area, etc). Contains the corrected position the client should snap back to.", + "direction": "outgoing", + "isDynamic": false, + "size": 8, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x21", + "description": "Packet identifier" + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Sequence number of the rejected movement request" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Correct X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Correct Y coordinate" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Correct facing direction (0-7)" + }, + { + "name": "Z", + "type": "sbyte", + "size": 1, + "description": "Correct Z coordinate" + } + ], + "related": [ + { + "id": "0x02", + "relationship": "request", + "note": "The movement request that was rejected" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 45 + } + }, + { + "id": "0x22", + "name": "Movement Acknowledgment", + "description": "Sent by the server to confirm successful player movement. Includes the player\u0027s current notoriety for display purposes.", + "direction": "outgoing", + "noMerge": true, + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x22", + "description": "Packet identifier" + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Sequence number of the accepted movement request" + }, + { + "name": "Notoriety", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Player\u0027s current 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" + } + ] + } + ], + "related": [ + { + "id": "0x02", + "relationship": "request", + "note": "The movement request that was accepted" + } + ], + "notes": "Not related to incoming 0x22 (Resynchronize) despite sharing the same packet ID.", + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 42 + } + }, + { + "id": "0x97", + "name": "Move Player", + "description": "Server-initiated player movement. Forces the client to move in a direction (used for pushback effects, conveyors, etc).", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x97", + "description": "Packet identifier" + }, + { + "name": "Direction", + "type": "byte", + "size": 1, + "description": "Direction to move (0-7). Bit 0x80 indicates running." + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 35 + } + }, + { + "id": "0xBF", + "subId": "0x26", + "name": "Speed Control", + "description": "Controls the player\u0027s movement speed. Used for mount speed changes, walk/run restrictions, etc.", + "direction": "outgoing", + "isDynamic": false, + "size": 6, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0026", + "description": "Sub-command for speed control" + }, + { + "name": "Speed Setting", + "type": "enum", + "size": 1, + "description": "Movement speed mode", + "values": [ + { "value": "0", "name": "Disable", "description": "Normal speed (remove override)" }, + { "value": "1", "name": "MountSpeed", "description": "Force mounted movement speed" }, + { "value": "2", "name": "WalkOnly", "description": "Force walk speed only" } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 31 + } + }, + { + "id": "0xF2", + "name": "Time Sync Response", + "description": "Server response to client time synchronization request. Contains tick counts for latency calculation.", + "direction": "outgoing", + "isDynamic": false, + "size": 25, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xF2", + "description": "Packet identifier" + }, + { + "name": "Tick Count1", + "type": "long", + "size": 8, + "description": "Server tick count" + }, + { + "name": "Tick Count2", + "type": "long", + "size": 8, + "description": "Server tick count" + }, + { + "name": "Tick Count3", + "type": "long", + "size": 8, + "description": "Server tick count" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 63 + } + } + ] +} diff --git a/docs/packets/outgoing/party.json b/docs/packets/outgoing/party.json new file mode 100644 index 000000000..0a173d9e4 --- /dev/null +++ b/docs/packets/outgoing/party.json @@ -0,0 +1,281 @@ +{ + "category": "Party", + "packets": [ + { + "id": "0xBF", + "subId": "0x06", + "name": "Party Message", + "description": "Party system messages with various subcommands.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Member List", + "version": "0x01", + "condition": "command == 0x01", + "size": "7 + (memberCount x 4)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Party subcommand" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Member list command" + }, + { + "name": "Member Count", + "type": "byte", + "size": 1, + "description": "Number of party members" + }, + { + "name": "Members", + "type": "loop", + "description": "Party members", + "loop": { + "countField": "memberCount", + "fields": [ + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Member\u0027s serial" + } + ] + } + } + ] + }, + { + "name": "Remove Member", + "version": "0x02", + "condition": "command == 0x02", + "size": "11 + (memberCount x 4)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Party subcommand" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x02", + "description": "Remove member command" + }, + { + "name": "Member Count", + "type": "byte", + "size": 1, + "description": "Number of remaining members" + }, + { + "name": "Removed Serial", + "type": "uint", + "size": 4, + "description": "Serial of removed member" + }, + { + "name": "Members", + "type": "loop", + "description": "Remaining party members", + "loop": { + "countField": "memberCount", + "fields": [ + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Member\u0027s serial" + } + ] + } + } + ] + }, + { + "name": "Private Message", + "version": "0x03", + "condition": "command == 0x03", + "size": "12 + (text.Length x 2)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Party subcommand" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x03", + "description": "Private message command" + }, + { + "name": "Sender Serial", + "type": "uint", + "size": 4, + "description": "Serial of message sender" + }, + { + "name": "Text", + "type": "utf16be-t", + "description": "Message text" + } + ] + }, + { + "name": "Public Message", + "version": "0x04", + "condition": "command == 0x04", + "size": "12 + (text.Length x 2)", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Party subcommand" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x04", + "description": "Public message command" + }, + { + "name": "Sender Serial", + "type": "uint", + "size": 4, + "description": "Serial of message sender" + }, + { + "name": "Text", + "type": "utf16be-t", + "description": "Message text" + } + ] + }, + { + "name": "Party Invitation", + "version": "0x07", + "condition": "command == 0x07", + "size": 10, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "10", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0006", + "description": "Party subcommand" + }, + { + "name": "Command", + "type": "byte", + "size": 1, + "value": "0x07", + "description": "Invitation command" + }, + { + "name": "Leader Serial", + "type": "uint", + "size": 4, + "description": "Serial of party leader" + } + ] + } + ], + "related": [ + { + "id": "0xBF/0x06", + "relationship": "request", + "note": "Party Message from client" + } + ], + "source": { + "file": "Projects/UOContent/Engines/Party/PartyPackets.cs", + "line": 28 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/player.json b/docs/packets/outgoing/player.json new file mode 100644 index 000000000..921a59323 --- /dev/null +++ b/docs/packets/outgoing/player.json @@ -0,0 +1,1057 @@ +{ + "category": "Player", + "packets": [ + { + "id": "0x23", + "name": "Drag Effect", + "description": "Displays a drag/drop visual effect between two points.", + "direction": "outgoing", + "isDynamic": false, + "size": 26, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x23", + "description": "Packet identifier" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Hue", + "type": "short", + "size": 2, + "description": "Item hue" + }, + { + "name": "Amount", + "type": "short", + "size": 2, + "description": "Item amount" + }, + { + "name": "Src Serial", + "type": "uint", + "size": 4, + "description": "Source entity serial" + }, + { + "name": "Src X", + "type": "short", + "size": 2, + "description": "Source X coordinate" + }, + { + "name": "Src Y", + "type": "short", + "size": 2, + "description": "Source Y coordinate" + }, + { + "name": "Src Z", + "type": "sbyte", + "size": 1, + "description": "Source Z coordinate" + }, + { + "name": "Dst Serial", + "type": "uint", + "size": 4, + "description": "Destination entity serial" + }, + { + "name": "Dst X", + "type": "short", + "size": 2, + "description": "Destination X coordinate" + }, + { + "name": "Dst Y", + "type": "short", + "size": 2, + "description": "Destination Y coordinate" + }, + { + "name": "Dst Z", + "type": "sbyte", + "size": 1, + "description": "Destination Z coordinate" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 198 + } + }, + { + "id": "0x27", + "name": "Lift Reject", + "description": "Server rejects a lift/pick up request.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x27", + "description": "Packet identifier" + }, + { + "name": "Reason", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Rejection reason", + "values": [ + { + "value": 0, + "name": "Cannot Lift", + "description": "You cannot pick that up" + }, + { + "value": 1, + "name": "Out Of Range", + "description": "That is out of range" + }, + { + "value": 2, + "name": "Out Of Sight", + "description": "That is out of sight" + }, + { + "value": 3, + "name": "Try To Steal", + "description": "That does not belong to you" + }, + { + "value": 4, + "name": "Are Holding", + "description": "You are already holding an item" + }, + { + "value": 5, + "name": "Inspecific", + "description": "You cannot pick that up" + } + ] + } + ], + "related": [ + { + "id": "0x07", + "relationship": "request", + "note": "Lift Request that was rejected" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 90 + } + }, + { + "id": "0x2C", + "name": "Death Status", + "description": "Notifies client of death/resurrection state.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x2C", + "description": "Packet identifier" + }, + { + "name": "Dead", + "type": "byte", + "size": 1, + "value": "0x02", + "description": "Always 2 (dead)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 63 + } + }, + { + "id": "0x38", + "name": "Pathfind Message", + "description": "Instructs client to pathfind to a location.", + "direction": "outgoing", + "isDynamic": false, + "size": 7, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x38", + "description": "Packet identifier" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "Target X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "Target Y coordinate" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "Target Z coordinate" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 319 + } + }, + { + "id": "0x3A", + "name": "Skills Update", + "description": "Sends full skills list or single skill update to client.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3A", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Update type", + "values": [ + { + "value": "0x00", + "name": "Full No Caps", + "description": "Full list without caps" + }, + { + "value": "0x02", + "name": "Full With Caps", + "description": "Full list with skill caps" + }, + { + "value": "0xDF", + "name": "Single With Caps", + "description": "Single skill update with cap" + }, + { + "value": "0xFF", + "name": "Single No Caps", + "description": "Single skill update" + } + ] + }, + { + "name": "Skills", + "type": "loop", + "loop": { + "until": "skillId == 0", + "fields": [ + { + "name": "Skill ID", + "type": "ushort", + "size": 2, + "description": "Skill ID + 1 (0 terminates)" + }, + { + "name": "Value", + "type": "ushort", + "size": 2, + "description": "Current skill value * 10" + }, + { + "name": "Base", + "type": "ushort", + "size": 2, + "description": "Base skill value * 10" + }, + { + "name": "Lock", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Skill lock state", + "values": [ + { + "value": 0, + "name": "Up", + "description": "Skill gains enabled" + }, + { + "value": 1, + "name": "Down", + "description": "Skill decreases enabled" + }, + { + "value": 2, + "name": "Locked", + "description": "Skill locked" + } + ] + }, + { + "name": "Cap", + "type": "ushort", + "size": 2, + "description": "Skill cap * 10 (if type includes caps)" + } + ] + } + } + ], + "related": [ + { + "id": "0x34", + "direction": "incoming", + "relationship": "request", + "note": "Mobile Query (skills) triggers this response" + }, + { + "id": "0x3A", + "direction": "incoming", + "relationship": "related", + "note": "Change Skill Lock may trigger update" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 121 + } + }, + { + "id": "0x5B", + "name": "Current Time", + "description": "Sends current server time to client.", + "direction": "outgoing", + "isDynamic": false, + "size": 4, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x5B", + "description": "Packet identifier" + }, + { + "name": "Hour", + "type": "byte", + "size": 1, + "description": "Hour (0-23)" + }, + { + "name": "Minute", + "type": "byte", + "size": 1, + "description": "Minute (0-59)" + }, + { + "name": "Second", + "type": "byte", + "size": 1, + "description": "Second (0-59)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 316 + } + }, + { + "id": "0x65", + "name": "Weather", + "description": "Sets weather conditions for client.", + "direction": "outgoing", + "isDynamic": false, + "size": 4, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x65", + "description": "Packet identifier" + }, + { + "name": "Type", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Weather type", + "values": [ + { + "value": 0, + "name": "Rain", + "description": "Raining" + }, + { + "value": 1, + "name": "Storm Brewing", + "description": "Storm brewing" + }, + { + "value": 2, + "name": "Snow", + "description": "Snowing" + }, + { + "value": 3, + "name": "Storm", + "description": "Storm in progress" + }, + { + "value": 254, + "name": "None", + "description": "No weather" + }, + { + "value": 255, + "name": "Clear", + "description": "Clear weather (stops current)" + } + ] + }, + { + "name": "Intensity", + "type": "byte", + "size": 1, + "description": "Weather intensity (0-255)" + }, + { + "name": "Temperature", + "type": "byte", + "size": 1, + "description": "Temperature value" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 97 + } + }, + { + "id": "0x6D", + "name": "Play Music", + "description": "Plays background music on client.", + "direction": "outgoing", + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6D", + "description": "Packet identifier" + }, + { + "name": "Music ID", + "type": "short", + "size": 2, + "description": "Music track ID (0x1FFF = stop)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 275 + } + }, + { + "id": "0x73", + "name": "Ping Ack", + "description": "Server acknowledges ping request.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x73", + "description": "Packet identifier" + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Ping sequence (echoed from request)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 336 + } + }, + { + "id": "0x76", + "name": "Server Change", + "description": "Notifies client of server/map transition.", + "direction": "outgoing", + "isDynamic": false, + "size": 16, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x76", + "description": "Packet identifier" + }, + { + "name": "X", + "type": "short", + "size": 2, + "description": "New X coordinate" + }, + { + "name": "Y", + "type": "short", + "size": 2, + "description": "New Y coordinate" + }, + { + "name": "Z", + "type": "short", + "size": 2, + "description": "New Z coordinate" + }, + { + "name": "Unknown", + "type": "byte", + "size": 1, + "value": "0x00", + "description": "Unknown" + }, + { + "name": "Unknown2", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Unknown" + }, + { + "name": "Unknown3", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Unknown" + }, + { + "name": "Map Width", + "type": "short", + "size": 2, + "description": "Map width" + }, + { + "name": "Map Height", + "type": "short", + "size": 2, + "description": "Map height" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 100 + } + }, + { + "id": "0x7B", + "name": "Sequence", + "description": "Sends sequence number to client for synchronization.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x7B", + "description": "Packet identifier" + }, + { + "name": "Sequence", + "type": "byte", + "size": 1, + "description": "Sequence number" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 154 + } + }, + { + "id": "0x88", + "name": "Display Paperdoll", + "description": "Opens paperdoll window for a mobile.", + "direction": "outgoing", + "isDynamic": false, + "size": 66, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x88", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile" + }, + { + "name": "Title", + "type": "ascii", + "size": 60, + "description": "Title/name displayed" + }, + { + "name": "Flags", + "type": "bitfield", + "size": 1, + "description": "Paperdoll flags", + "flags": [ + { + "bit": "0", + "name": "Warmode", + "description": "Mobile is in war mode" + }, + { + "bit": "1", + "name": "Can Lift", + "description": "Viewer can lift equipment" + } + ] + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 247 + } + }, + { + "id": "0x95", + "name": "Display Hue Picker", + "description": "Opens hue picker dialog on client.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x95", + "description": "Packet identifier" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Hue picker serial" + }, + { + "name": "Unknown", + "type": "short", + "size": 2, + "value": "0x0000", + "description": "Unknown" + }, + { + "name": "Item ID", + "type": "short", + "size": 2, + "description": "Item graphic to preview hue on" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 338 + } + }, + { + "id": "0xA5", + "name": "Launch Browser", + "description": "Opens a URL in client\u0027s web browser.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA5", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "URL", + "type": "ascii-t", + "description": "URL to open" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 180 + } + }, + { + "id": "0xA6", + "name": "Scroll Message", + "description": "Displays a scrollable tips/message window.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xA6", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Type", + "type": "byte", + "size": 1, + "description": "Scroll type" + }, + { + "name": "Tip Number", + "type": "int", + "size": 4, + "description": "Tip/message number" + }, + { + "name": "Text Length", + "type": "ushort", + "size": 2, + "description": "Length of text" + }, + { + "name": "Text", + "type": "ascii", + "description": "Message text" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 291 + } + }, + { + "id": "0xB8", + "name": "Display Profile", + "description": "Displays a mobile\u0027s profile.", + "direction": "outgoing", + "isDynamic": true, + "size": "var", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xB8", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Serial", + "type": "uint", + "size": 4, + "description": "Serial of mobile" + }, + { + "name": "Header", + "type": "ascii-t", + "description": "Profile header" + }, + { + "name": "Footer", + "type": "utf16be-t", + "description": "Profile footer" + }, + { + "name": "Body", + "type": "utf16be-t", + "description": "Profile body text" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 66 + } + }, + { + "id": "0xBC", + "name": "Season Change", + "description": "Changes the visual season on client.", + "direction": "outgoing", + "isDynamic": false, + "size": 3, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBC", + "description": "Packet identifier" + }, + { + "name": "Season", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Season value", + "values": [ + { + "value": 0, + "name": "Spring", + "description": "Spring season" + }, + { + "value": 1, + "name": "Summer", + "description": "Summer season" + }, + { + "value": 2, + "name": "Fall", + "description": "Fall/Autumn season" + }, + { + "value": 3, + "name": "Winter", + "description": "Winter season" + }, + { + "value": 4, + "name": "Desolation", + "description": "Desolation (dead trees)" + } + ] + }, + { + "name": "Play Sound", + "type": "bool", + "size": 1, + "description": "Play season change sound" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 244 + } + }, + { + "id": "0xBF/0x19", + "name": "Stat Lock Info", + "description": "Sends stat lock states (STR/DEX/INT) to client.", + "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": [ + { + "bit": "5-4", + "name": "Str Lock", + "description": "Strength lock (value \u003c\u003c 4)" + }, + { + "bit": "3-2", + "name": "Dex Lock", + "description": "Dexterity lock (value \u003c\u003c 2)" + }, + { + "bit": "1-0", + "name": "Int Lock", + "description": "Intelligence lock (value \u003c\u003c 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" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 36 + } + }, + { + "id": "0xC8", + "name": "Change Update Range", + "description": "Sets the client\u0027s update range.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xC8", + "description": "Packet identifier" + }, + { + "name": "Range", + "type": "byte", + "size": 1, + "description": "Update range (typically 18)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 59 + } + }, + { + "id": "0xD1", + "name": "Logout Ack", + "description": "Server acknowledges logout request.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xD1", + "description": "Packet identifier" + }, + { + "name": "Ack", + "type": "byte", + "size": 1, + "value": "0x01", + "description": "Acknowledgment (1 = OK)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 94 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/securetrade.json b/docs/packets/outgoing/securetrade.json new file mode 100644 index 000000000..1a0e1d9e4 --- /dev/null +++ b/docs/packets/outgoing/securetrade.json @@ -0,0 +1,275 @@ +{ + "category": "Secure Trade", + "packets": [ + { + "id": "0x6F", + "name": "Secure Trade", + "description": "Manages secure trade windows between players.", + "direction": "outgoing", + "isDynamic": true, + "size": "Varies", + "variants": [ + { + "name": "Display Trade Window", + "condition": "flag == Display (0)", + "size": 47, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "47", + "description": "Packet length" + }, + { + "name": "Flag", + "type": "enum", + "enumType": "sequential", + "size": 1, + "value": "0", + "description": "Trade action flag", + "values": [ + { + "value": 0, + "name": "Display", + "description": "Open trade window" + }, + { + "value": 1, + "name": "Close", + "description": "Close trade window" + }, + { + "value": 2, + "name": "Update", + "description": "Update accept status" + }, + { + "value": 3, + "name": "Update Gold", + "description": "Update gold amounts" + }, + { + "value": 4, + "name": "Update Ledger", + "description": "Update ledger" + } + ] + }, + { + "name": "Partner Serial", + "type": "uint", + "size": 4, + "description": "Serial of trading partner" + }, + { + "name": "First Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of your trade container" + }, + { + "name": "Second Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of partner\u0027s trade container" + }, + { + "name": "Has Name", + "type": "bool", + "size": 1, + "value": "true", + "description": "Name field follows" + }, + { + "name": "Partner Name", + "type": "ascii", + "size": 30, + "description": "Trading partner\u0027s name" + } + ] + }, + { + "name": "Close Trade Window", + "condition": "flag == Close (1)", + "size": 17, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "17", + "description": "Packet length" + }, + { + "name": "Flag", + "type": "byte", + "size": 1, + "value": "1", + "description": "Close flag" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Trade container serial" + }, + { + "name": "Unused1", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Unused2", + "type": "int", + "size": 4, + "value": "0", + "description": "Unused" + }, + { + "name": "Has Name", + "type": "bool", + "size": 1, + "value": "false", + "description": "No name follows" + } + ] + }, + { + "name": "Update Accept Status", + "condition": "flag == Update (2)", + "size": 17, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "17", + "description": "Packet length" + }, + { + "name": "Flag", + "type": "byte", + "size": 1, + "value": "2", + "description": "Update flag" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Trade container serial" + }, + { + "name": "Your Accept", + "type": "int", + "size": 4, + "description": "Your accept status (0 or 1)" + }, + { + "name": "Partner Accept", + "type": "int", + "size": 4, + "description": "Partner\u0027s accept status (0 or 1)" + }, + { + "name": "Has Name", + "type": "bool", + "size": 1, + "value": "false", + "description": "No name follows" + } + ] + }, + { + "name": "Update Gold/Platinum", + "condition": "flag == UpdateGold (3)", + "size": 17, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6F", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "17", + "description": "Packet length" + }, + { + "name": "Flag", + "type": "byte", + "size": 1, + "value": "3", + "description": "UpdateGold flag" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Trade container serial" + }, + { + "name": "Gold", + "type": "int", + "size": 4, + "description": "Gold amount" + }, + { + "name": "Platinum", + "type": "int", + "size": 4, + "description": "Platinum amount" + }, + { + "name": "Has Name", + "type": "bool", + "size": 1, + "value": "false", + "description": "No name follows" + } + ] + } + ], + "related": [ + { + "id": "0x6F", + "direction": "incoming", + "relationship": "request", + "note": "Client trade actions" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingSecureTradePackets.cs", + "line": 32 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/targeting.json b/docs/packets/outgoing/targeting.json new file mode 100644 index 000000000..4e6fd478f --- /dev/null +++ b/docs/packets/outgoing/targeting.json @@ -0,0 +1,221 @@ +{ + "category": "Targeting", + "packets": [ + { + "id": "0x6C", + "name": "Target Request", + "description": "Requests the client to select a target.", + "direction": "outgoing", + "isDynamic": false, + "size": 19, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x6C", + "description": "Packet identifier" + }, + { + "name": "Allow Ground", + "type": "bool", + "size": 1, + "description": "True = allow ground targeting" + }, + { + "name": "Target ID", + "type": "int", + "size": 4, + "description": "Target cursor ID for matching response" + }, + { + "name": "Flags", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Target cursor flags", + "values": [ + { + "value": 0, + "name": "Neutral", + "description": "Neutral targeting (gray cursor)" + }, + { + "value": 1, + "name": "Harmful", + "description": "Harmful action (red cursor)" + }, + { + "value": 2, + "name": "Beneficial", + "description": "Beneficial action (green cursor)" + }, + { + "value": 3, + "name": "Cancel", + "description": "Cancel targeting" + } + ] + }, + { + "name": "Padding", + "type": "byte[]", + "size": 12, + "description": "Padding (zeros)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingTargetPackets.cs", + "line": 57 + } + }, + { + "id": "0x99", + "name": "Multi Target Request", + "description": "Requests the client to place a multi (house/boat) structure.", + "direction": "outgoing", + "isDynamic": false, + "size": "Varies", + "variants": [ + { + "version": "pre-HighSeas", + "name": "Classic", + "size": 26, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x99", + "description": "Packet identifier" + }, + { + "name": "Allow Ground", + "type": "bool", + "size": 1, + "description": "Allow ground targeting" + }, + { + "name": "Target ID", + "type": "int", + "size": 4, + "description": "Target cursor ID" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Target cursor flags" + }, + { + "name": "Padding", + "type": "byte[]", + "size": 11, + "description": "Padding (zeros)" + }, + { + "name": "Multi ID", + "type": "short", + "size": 2, + "description": "Multi graphic ID" + }, + { + "name": "Offset X", + "type": "short", + "size": 2, + "description": "X offset for placement" + }, + { + "name": "Offset Y", + "type": "short", + "size": 2, + "description": "Y offset for placement" + }, + { + "name": "Offset Z", + "type": "short", + "size": 2, + "description": "Z offset for placement" + } + ] + }, + { + "version": "HighSeas+", + "name": "High Seas Extended", + "condition": "Client version \u003e= 7.0.9.0 (HighSeas)", + "size": 30, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x99", + "description": "Packet identifier" + }, + { + "name": "Allow Ground", + "type": "bool", + "size": 1, + "description": "Allow ground targeting" + }, + { + "name": "Target ID", + "type": "int", + "size": 4, + "description": "Target cursor ID" + }, + { + "name": "Flags", + "type": "byte", + "size": 1, + "description": "Target cursor flags" + }, + { + "name": "Padding", + "type": "byte[]", + "size": 11, + "description": "Padding (zeros)" + }, + { + "name": "Multi ID", + "type": "short", + "size": 2, + "description": "Multi graphic ID" + }, + { + "name": "Offset X", + "type": "short", + "size": 2, + "description": "X offset for placement" + }, + { + "name": "Offset Y", + "type": "short", + "size": 2, + "description": "Y offset for placement" + }, + { + "name": "Offset Z", + "type": "short", + "size": 2, + "description": "Z offset for placement" + }, + { + "name": "Unknown", + "type": "int", + "size": 4, + "description": "Unknown (HighSeas extension)" + } + ] + } + ], + "clientVersion": { + "feature": "HighSeas adds 4 bytes" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingTargetPackets.cs", + "line": 23 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/vendor.json b/docs/packets/outgoing/vendor.json new file mode 100644 index 000000000..2691f93a7 --- /dev/null +++ b/docs/packets/outgoing/vendor.json @@ -0,0 +1,216 @@ +{ + "category": "Vendor", + "packets": [ + { + "id": "0x3B", + "name": "End Vendor Transaction", + "description": "Ends a vendor buy or sell transaction.", + "direction": "outgoing", + "isDynamic": false, + "size": 8, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x3B", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "8", + "description": "Packet length" + }, + { + "name": "Vendor Serial", + "type": "uint", + "size": 4, + "description": "Serial of the vendor" + }, + { + "name": "Item Count", + "type": "byte", + "size": 1, + "value": "0", + "description": "Item count (0 = end transaction)" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs", + "line": 111 + } + }, + { + "id": "0x74", + "name": "Vendor Buy List", + "description": "Sends the list of items available for purchase from a vendor with prices.", + "direction": "outgoing", + "isDynamic": true, + "size": "8+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x74", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Container Serial", + "type": "uint", + "size": 4, + "description": "Serial of vendor\u0027s buy container" + }, + { + "name": "Item Count", + "type": "byte", + "size": 1, + "description": "Number of items" + }, + { + "name": "Items", + "type": "loop", + "description": "Buy items with prices", + "loop": { + "countField": "itemCount", + "fields": [ + { + "name": "Price", + "type": "int", + "size": 4, + "description": "Item price" + }, + { + "name": "Desc Length", + "type": "byte", + "size": 1, + "description": "Description length + 1" + }, + { + "name": "Description", + "type": "ascii-t", + "description": "Item description" + } + ] + } + } + ], + "related": [ + { + "id": "0x3C", + "relationship": "request", + "note": "Container Content with items" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingVendorBuyPackets.cs", + "line": 77 + } + }, + { + "id": "0x9E", + "name": "Vendor Sell List", + "description": "Sends the list of items the vendor will buy from the player.", + "direction": "outgoing", + "isDynamic": true, + "size": "9+", + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0x9E", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "description": "Packet length" + }, + { + "name": "Vendor Serial", + "type": "uint", + "size": 4, + "description": "Serial of the vendor" + }, + { + "name": "Item Count", + "type": "ushort", + "size": 2, + "description": "Number of items" + }, + { + "name": "Items", + "type": "loop", + "description": "Sell items with prices", + "loop": { + "countField": "itemCount", + "fields": [ + { + "name": "Item Serial", + "type": "uint", + "size": 4, + "description": "Item serial" + }, + { + "name": "Item ID", + "type": "ushort", + "size": 2, + "description": "Item graphic ID" + }, + { + "name": "Hue", + "type": "ushort", + "size": 2, + "description": "Item hue" + }, + { + "name": "Amount", + "type": "ushort", + "size": 2, + "description": "Item amount" + }, + { + "name": "Price", + "type": "ushort", + "size": 2, + "description": "Price per unit" + }, + { + "name": "Name Length", + "type": "ushort", + "size": 2, + "description": "Name length" + }, + { + "name": "Name", + "type": "ascii", + "description": "Item name" + } + ] + } + } + ], + "related": [ + { + "id": "0x9F", + "relationship": "response", + "note": "Vendor Sell Reply from client" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingVendorSellPackets.cs", + "line": 25 + } + } + ] +} \ No newline at end of file diff --git a/docs/packets/outgoing/weaponability.json b/docs/packets/outgoing/weaponability.json new file mode 100644 index 000000000..3c54691c3 --- /dev/null +++ b/docs/packets/outgoing/weaponability.json @@ -0,0 +1,89 @@ +{ + "category": "Weapon Ability", + "packets": [ + { + "id": "0xBF", + "subId": "0x21", + "name": "Clear Weapon Ability", + "description": "Clears the currently selected weapon ability.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "5", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0021", + "description": "Clear Weapon Ability subcommand" + } + ], + "source": { + "file": "Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs", + "line": 37 + } + }, + { + "id": "0xBF", + "subId": "0x25", + "name": "Toggle Special Ability", + "description": "Toggles a special weapon ability on or off.", + "direction": "outgoing", + "isDynamic": false, + "size": 8, + "fields": [ + { + "name": "Packet ID", + "type": "byte", + "size": 1, + "value": "0xBF", + "description": "Packet identifier" + }, + { + "name": "Length", + "type": "ushort", + "size": 2, + "value": "8", + "description": "Packet length" + }, + { + "name": "Sub-Command", + "type": "ushort", + "size": 2, + "value": "0x0025", + "description": "Toggle Special Ability subcommand" + }, + { + "name": "Ability ID", + "type": "short", + "size": 2, + "description": "Ability ID" + }, + { + "name": "Active", + "type": "bool", + "size": 1, + "description": "True if ability is active" + } + ], + "source": { + "file": "Projects/UOContent/Items/Weapons/Abilities/WeaponAbilityPackets.cs", + "line": 40 + } + } + ] +} diff --git a/docs/packets/packets.html b/docs/packets/packets.html new file mode 100644 index 000000000..b2054a0e7 --- /dev/null +++ b/docs/packets/packets.html @@ -0,0 +1,1533 @@ + + + + + + + + + ModernUO Packet Documentation + + + + + + + +
+ +
+
+
+ +
+

ModernUO Packet Documentation

+

Ultima Online Network Protocol Reference

+
+
+
+ + +
+
+
+ + +
+ + + + +
+
+ +
+
📦
+

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 new file mode 100644 index 000000000..9e25876c0 --- /dev/null +++ b/docs/packets/template.html @@ -0,0 +1,1532 @@ + + + + + + + + + ModernUO Packet Documentation + + + + + + + +
+ +
+
+
+ +
+

ModernUO Packet Documentation

+

Ultima Online Network Protocol Reference

+
+
+
+ + +
+
+
+ + +
+ + + + +
+
+ +
+
📦
+

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/tools/build-packets.ps1 b/docs/tools/build-packets.ps1 new file mode 100644 index 000000000..d1f25538b --- /dev/null +++ b/docs/tools/build-packets.ps1 @@ -0,0 +1,175 @@ +# build-packets.ps1 +# Combines all packet JSON files with the HTML template to generate the final documentation page. +# +# Usage: +# .\build-packets.ps1 +# .\build-packets.ps1 -OutputPath "C:\custom\output\packets.html" + +param( + [string]$OutputPath = "" +) + +$ErrorActionPreference = "Stop" + +# Determine paths +$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path +$docsDir = (Resolve-Path (Join-Path $scriptDir "..")).Path +$packetsDir = Join-Path $docsDir "packets" +$templateFile = Join-Path $packetsDir "template.html" + +if (-not $OutputPath) { + $OutputPath = Join-Path $packetsDir "packets.html" +} + +Write-Host "ModernUO Packet Documentation Builder" -ForegroundColor Cyan +Write-Host "======================================" -ForegroundColor Cyan +Write-Host "" + +# Verify template exists +if (-not (Test-Path $templateFile)) { + Write-Error "Template file not found: $templateFile" + exit 1 +} + +# Collect all packet JSON files +$allPackets = @{ + incoming = @() + outgoing = @() +} + +$incomingDir = Join-Path $packetsDir "incoming" +$outgoingDir = Join-Path $packetsDir "outgoing" + +# Read incoming packets +if (Test-Path $incomingDir) { + $incomingFiles = Get-ChildItem "$incomingDir\*.json" -ErrorAction SilentlyContinue + foreach ($file in $incomingFiles) { + Write-Host " Reading: $($file.Name)" -ForegroundColor Gray + try { + $content = Get-Content $file.FullName -Raw -Encoding UTF8 + $data = $content | ConvertFrom-Json + if ($data.packets) { + # Add category and merge tags for each packet + foreach ($packet in $data.packets) { + # Add category if not present (backward compatibility) + if (-not $packet.category -and $data.category) { + $packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -Force + } + + # Merge tags: file-level + packet-level + $fileTags = @() + if ($data.tags) { $fileTags = @($data.tags) } + + $packetTags = @() + if ($packet.tags) { $packetTags = @($packet.tags) } + + $allTags = @($fileTags + $packetTags) | Select-Object -Unique + + # Always include the primary category as a tag (first position) + if ($data.category -and $data.category -notin $allTags) { + $allTags = @($data.category) + $allTags + } + + # Ensure tags is always an array (PowerShell can collapse single-element arrays) + $allTags = @($allTags) + + $packet | Add-Member -NotePropertyName "tags" -NotePropertyValue $allTags -Force + } + $allPackets.incoming += $data.packets + } + } catch { + Write-Warning "Failed to parse $($file.Name): $_" + } + } + Write-Host " Found $($allPackets.incoming.Count) incoming packets" -ForegroundColor Green +} else { + Write-Host " No incoming packets directory found" -ForegroundColor Yellow +} + +# Read outgoing packets +if (Test-Path $outgoingDir) { + $outgoingFiles = Get-ChildItem "$outgoingDir\*.json" -ErrorAction SilentlyContinue + foreach ($file in $outgoingFiles) { + Write-Host " Reading: $($file.Name)" -ForegroundColor Gray + try { + $content = Get-Content $file.FullName -Raw -Encoding UTF8 + $data = $content | ConvertFrom-Json + if ($data.packets) { + # Add category and merge tags for each packet + foreach ($packet in $data.packets) { + # Add category if not present (backward compatibility) + if (-not $packet.category -and $data.category) { + $packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -Force + } + + # Merge tags: file-level + packet-level + $fileTags = @() + if ($data.tags) { $fileTags = @($data.tags) } + + $packetTags = @() + if ($packet.tags) { $packetTags = @($packet.tags) } + + $allTags = @($fileTags + $packetTags) | Select-Object -Unique + + # Always include the primary category as a tag (first position) + if ($data.category -and $data.category -notin $allTags) { + $allTags = @($data.category) + $allTags + } + + # Ensure tags is always an array (PowerShell can collapse single-element arrays) + $allTags = @($allTags) + + $packet | Add-Member -NotePropertyName "tags" -NotePropertyValue $allTags -Force + } + $allPackets.outgoing += $data.packets + } + } catch { + Write-Warning "Failed to parse $($file.Name): $_" + } + } + Write-Host " Found $($allPackets.outgoing.Count) outgoing packets" -ForegroundColor Green +} else { + Write-Host " No outgoing packets directory found" -ForegroundColor Yellow +} + +$totalPackets = $allPackets.incoming.Count + $allPackets.outgoing.Count +Write-Host "" +Write-Host "Total packets: $totalPackets" -ForegroundColor Cyan + +if ($totalPackets -eq 0) { + Write-Warning "No packets found! The output will have empty documentation." +} + +# Convert to JSON +$packetsJson = $allPackets | ConvertTo-Json -Depth 20 -Compress + +# HTML entity escape the JSON to safely embed in HTML +$packetsJson = $packetsJson -replace '<', '<' -replace '>', '>' + +# Read template and inject JSON +Write-Host "" +Write-Host "Reading template..." -ForegroundColor Gray +$template = Get-Content $templateFile -Raw -Encoding UTF8 + +Write-Host "Injecting packet data..." -ForegroundColor Gray +$output = $template -replace '', $packetsJson + +# Ensure output directory exists +$outputDir = Split-Path $OutputPath -Parent +if (-not (Test-Path $outputDir)) { + Write-Host "Creating output directory: $outputDir" -ForegroundColor Gray + New-Item -ItemType Directory -Path $outputDir -Force | Out-Null +} + +# Write output +Write-Host "Writing output..." -ForegroundColor Gray +$output | Set-Content $OutputPath -Encoding UTF8 + +$outputSize = (Get-Item $OutputPath).Length +$outputSizeKB = [math]::Round($outputSize / 1024, 2) + +Write-Host "" +Write-Host "Success!" -ForegroundColor Green +Write-Host " Output: $OutputPath" -ForegroundColor White +Write-Host " Size: $outputSizeKB KB" -ForegroundColor White +Write-Host " Packets: $totalPackets" -ForegroundColor White