diff --git a/Distribution/Data/packets.html b/Distribution/Data/packets.html new file mode 100644 index 000000000..c86194fae --- /dev/null +++ b/Distribution/Data/packets.html @@ -0,0 +1,735 @@ + + + + + + + + + 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/Distribution/Data/packets/CONVENTIONS.md b/Distribution/Data/packets/CONVENTIONS.md new file mode 100644 index 000000000..8c6a566f2 --- /dev/null +++ b/Distribution/Data/packets/CONVENTIONS.md @@ -0,0 +1,116 @@ +# Packet Documentation Conventions + +## String Types + +When documenting packet fields, use these specific type names to indicate the encoding and format: + +### By Encoding + +| Type | Encoding | Description | +|------|----------|-------------| +| `ascii` | ASCII | 7-bit ASCII characters | +| `unicode-le` | Unicode (Little Endian) | UTF-16LE, each character is 2 bytes | +| `unicode-be` | Unicode (Big Endian) | UTF-16BE, each character is 2 bytes | +| `utf8` | UTF-8 | Variable-width encoding (rarely used, mainly book packets) | + +### By Format + +| Suffix | Format | Example | +|--------|--------|---------| +| (no suffix) | Fixed length, padded/truncated | `ascii` with `size: 30` = exactly 30 bytes | +| `-null` | Null-terminated | `ascii-null` = string followed by 0x00 | +| `-prefixed` | Length-prefixed | `unicode-le-prefixed` = ushort length + characters | + +### Common Combinations + +| Full Type | Description | SpanWriter Method | +|-----------|-------------|-------------------| +| `ascii` | Fixed-length ASCII | `WriteAscii(text, maxLength)` | +| `ascii-null` | Null-terminated ASCII | `WriteAsciiNull(text)` | +| `unicode-le` | Fixed-length Unicode LE | `WriteLittleUni(text, maxLength)` | +| `unicode-le-null` | Null-terminated Unicode LE | `WriteLittleUniNull(text)` | +| `unicode-be` | Fixed-length Unicode BE | `WriteBigUni(text, maxLength)` | +| `unicode-be-null` | Null-terminated Unicode BE | `WriteBigUniNull(text)` | +| `utf8-null` | Null-terminated UTF-8 | `WriteUtf8Null(text)` | + +### Size Calculations + +- **Fixed ASCII**: Size in bytes = specified size +- **Fixed Unicode**: Size in bytes = specified size (characters) * 2 +- **Null-terminated**: Size = string length + 1 (ASCII) or string length * 2 + 2 (Unicode) +- **Length-prefixed**: Size = 2 (ushort length) + string data + +### Examples in JSON + +```json +// Fixed-length ASCII (30 bytes exactly) +{ "name": "characterName", "type": "ascii", "size": 30, "description": "Character name" } + +// Null-terminated ASCII (variable length) +{ "name": "message", "type": "ascii-null", "description": "Chat message" } + +// Fixed-length Unicode Little Endian +{ "name": "text", "type": "unicode-le", "size": 64, "description": "Unicode text (64 chars)" } + +// Null-terminated Unicode Big Endian +{ "name": "affix", "type": "unicode-be-null", "description": "Affix string" } +``` + +## Numeric Types + +| Type | Size | Range | Signed | +|------|------|-------|--------| +| `byte` | 1 | 0-255 | No | +| `sbyte` | 1 | -128 to 127 | Yes | +| `short` | 2 | -32768 to 32767 | Yes | +| `ushort` | 2 | 0-65535 | No | +| `int` | 4 | -2^31 to 2^31-1 | Yes | +| `uint` | 4 | 0 to 2^32-1 | No | +| `long` | 8 | -2^63 to 2^63-1 | Yes | +| `ulong` | 8 | 0 to 2^64-1 | No | +| `bool` | 1 | 0 (false) or 1 (true) | N/A | + +## Byte Order + +- All numeric types are **Big Endian** (network byte order) unless noted otherwise +- IP addresses use Little Endian (marked with `LE` suffix) +- Some client-specific fields may use Little Endian (always documented) + +## Packet Flags + +Common flag values used in mobile/item packets: + +| Flag | Value | Description | +|------|-------|-------------| +| Hidden | 0x80 | Entity is hidden | +| Poisoned | 0x04 | Mobile is poisoned | +| Blessed | 0x08 | Mobile is blessed/invulnerable | +| Warmode | 0x40 | Mobile is in war mode | +| Female | 0x02 | Mobile is female | + +## Direction Values + +| Value | Direction | +|-------|-----------| +| 0 | North | +| 1 | Right (NE) | +| 2 | East | +| 3 | Down (SE) | +| 4 | South | +| 5 | Left (SW) | +| 6 | West | +| 7 | Up (NW) | +| 0x80 | Running flag (OR with direction) | + +## Notoriety Values + +| Value | Name | Color | +|-------|------|-------| +| 0 | Invalid | Gray | +| 1 | Innocent | Blue | +| 2 | Ally/Friend | Green | +| 3 | Gray/Attackable | Gray | +| 4 | Criminal | Gray | +| 5 | Enemy | Orange | +| 6 | Murderer | Red | +| 7 | Invulnerable | Yellow | diff --git a/Distribution/Data/packets/PACKET_TRACKING.md b/Distribution/Data/packets/PACKET_TRACKING.md new file mode 100644 index 000000000..47f1f7b2b --- /dev/null +++ b/Distribution/Data/packets/PACKET_TRACKING.md @@ -0,0 +1,505 @@ +# Packet Documentation Tracking + +## Protocol Version Reference + +### Client Version → ProtocolChanges Mapping +| Version | Flag | Description | +|---------|------|-------------| +| 5.0.0a | NewSpellbook | AOS spellbook format (0xBF/0x1B) | +| 5.0.0a | DamagePacket | Damage packet (0x0B) | +| 5.0.2b | BuffIcon | Buff/debuff icons | +| 6.0.0.0 | NewHaven | New Haven starting city | +| **6.0.1.7** | **ContainerGridLines** | Container item grid positions (+1 byte per item) | +| 6.0.14.2 | ExtendedSupportedFeatures | 0xB9 uses 4 bytes instead of 2 | +| 7.0.0.0 | StygianAbyss | SA client features, 0xF3 world entity | +| 7.0.9.0 | HighSeas | HS features, extended 0xF3 | +| 7.0.13.0 | NewCharacterList | Extended city info in 0xA9 | +| 7.0.16.0 | NewCharacterCreation | 4th skill slot | +| 7.0.30.0 | ExtendedStatus | Mobile status version 6 | +| 7.0.33.1 | NewMobileIncoming | 0x78 always includes hue | +| 7.0.45.65 | NewSecureTrading | New secure trade format | +| 7.0.50.0 | UltimaStore | Ultima Store packets | +| 7.0.61.0 | EndlessJourney | EJ features | + +### Mobile Status Versions (Expansion-based) +| Version | Expansion | Size | Description | +|---------|-----------|------|-------------| +| 0 | Any | 43 | Compact (viewing others) | +| 3 | Pre-AOS | 70 | Basic stats | +| 4 | AOS | 88 | Resistances, luck, damage | +| 5 | ML | 91 | Weight, race | +| 6 | HS | 121 | Extended AOS status | + +--- + +## Incoming Packets Tracking + +### Account (IncomingAccountPackets.cs) +- [x] 0x00 - Create Character (Old, 104 bytes) +- [x] 0x5D - Play Character +- [x] 0x80 - Account Login +- [x] 0x83 - Delete Character +- [x] 0x91 - Game Login +- [x] 0xA0 - Play Server +- [x] 0xBD - Client Version (response) +- [x] 0xE1 - Client Type +- [x] 0xEF - Login Server Seed +- [x] 0xF8 - Create Character (New, 106 bytes) + +### Movement (IncomingMovementPackets.cs) +- [x] 0x02 - Movement Request + +### Entity (IncomingEntityPackets.cs) +- [x] 0x06 - Use Request (Double-Click) +- [x] 0x09 - Look Request (Single-Click) +- [x] 0xB6 - Object Help Request +- [x] 0xD6 - Batch Query Properties + +### Item (IncomingItemPackets.cs) +- [ ] 0x07 - Lift Request +- [ ] 0x08 - Drop Request (VERSION: 6017 adds grid location byte) +- [ ] 0x13 - Equip Request +- [ ] 0xEC - Equip Macro +- [ ] 0xED - Unequip Macro + +### Mobile (IncomingMobilePackets.cs) +- [ ] 0x6F - Secure Trade +- [ ] 0x75 - Rename Request +- [ ] 0x98 - Mobile Name Request (incoming) + +### Player (IncomingPlayerPackets.cs) +- [ ] 0x01 - Disconnect +- [ ] 0x05 - Attack Request +- [ ] 0x12 - Text Command (skills, cast) +- [ ] 0x22 - Resynchronize +- [ ] 0x2C - Death Status Response +- [ ] 0x34 - Mobile Query +- [ ] 0x3A - Change Skill Lock +- [ ] 0x72 - Set War Mode +- [ ] 0x73 - Ping Request +- [ ] 0x7D - Menu Response +- [ ] 0x95 - Hue Picker Response +- [ ] 0x9A - ASCII Prompt Response +- [ ] 0x9B - Help Request +- [ ] 0xA4 - System Info +- [ ] 0xA7 - Request Scroll Window +- [ ] 0xC2 - Unicode Prompt Response +- [ ] 0xC8 - Set Update Range +- [ ] 0xD0 - Configuration File +- [ ] 0xD1 - Logout Request +- [ ] 0xD7 - Encoded Command (wrapper) +- [ ] 0xF4 - Crash Report + +### Message (IncomingMessagePackets.cs) +- [ ] 0x03 - ASCII Speech +- [ ] 0xAD - Unicode Speech + +### Vendor (IncomingVendorPackets.cs) +- [ ] 0x3B - Vendor Buy Reply +- [ ] 0x9F - Vendor Sell Reply + +### Targeting (IncomingTargetingPackets.cs) +- [ ] 0x6C - Target Response + +### House (IncomingHousePackets.cs) +- [ ] 0xFB - Show Public House Content + +### Extended Commands (IncomingExtendedCommandPackets.cs) - 0xBF subpackets +- [ ] 0xBF/0x05 - Screen Size +- [ ] 0xBF/0x06 - Party Message +- [ ] 0xBF/0x09 - Disarm Request +- [ ] 0xBF/0x0A - Stun Request +- [ ] 0xBF/0x0B - Language +- [ ] 0xBF/0x0C - Close Status +- [ ] 0xBF/0x0E - Animate +- [ ] 0xBF/0x0F - Empty (unused) +- [ ] 0xBF/0x10 - Query Properties +- [ ] 0xBF/0x13 - Context Menu Request +- [ ] 0xBF/0x15 - Context Menu Response +- [ ] 0xBF/0x1A - Stat Lock Change +- [ ] 0xBF/0x1C - Cast Spell +- [ ] 0xBF/0x1E - Query Design Details +- [ ] 0xBF/0x24 - Unhandled BF +- [ ] 0xBF/0x2A - Race Change Reply +- [ ] 0xBF/0x2C - Bandage Target +- [ ] 0xBF/0x2D - Targeted Spell +- [ ] 0xBF/0x2E - Targeted Skill Use +- [ ] 0xBF/0x30 - Target By Resource Macro +- [ ] 0xBF/0x32 - Toggle Flying + +### Encoded Commands (0xD7 subpackets) +- [ ] 0xD7/0x02 - House Designer Backup +- [ ] 0xD7/0x03 - House Designer Restore +- [ ] 0xD7/0x04 - House Designer Commit +- [ ] 0xD7/0x05 - House Designer Delete +- [ ] 0xD7/0x06 - House Designer Build +- [ ] 0xD7/0x0C - House Designer Close +- [ ] 0xD7/0x0D - House Designer Stairs +- [ ] 0xD7/0x0E - House Designer Sync +- [ ] 0xD7/0x10 - House Designer Clear +- [ ] 0xD7/0x12 - House Designer Level +- [ ] 0xD7/0x13 - House Designer Roof +- [ ] 0xD7/0x14 - House Designer Roof Delete +- [ ] 0xD7/0x19 - Set Ability +- [ ] 0xD7/0x1A - House Designer Revert +- [ ] 0xD7/0x28 - Guild Gump Request +- [ ] 0xD7/0x32 - Quest Gump Request + +### Gumps (GumpSystem.cs) +- [ ] 0xB1 - Display Gump Response + +### Books (BookPackets.cs) +- [ ] 0x66 - Book Content Change +- [ ] 0x93 - Old Book Header Change +- [ ] 0xD4 - Book Header Change + +### Bulletin Boards (BulletinBoardPackets.cs) +- [ ] 0x71 - Bulletin Board Request + +### Maps (MapItemPackets.cs) +- [ ] 0x56 - Map Command + +### Mahjong (MahjongPackets.cs) +- [ ] 0xDA - Mahjong (with subcommands) + +### Chat (ChatPackets.cs) +- [ ] 0xB3 - Chat Action +- [ ] 0xB5 - Open Chat Window Request + +### Ultima Store (UltimaStorePackets.cs) +- [ ] 0xFA - Ultima Store Open Request + +### Hardware Info (HardwareInfo.cs) +- [ ] 0xD9 - Hardware Info + +### Assistants (AssistantHandler.cs) +- [ ] 0xBE - Assistant Version + +### Tracking (Tracking.cs) +- [ ] 0xBF/0x07 - Quest Arrow Click + +--- + +## Outgoing Packets Tracking + +### Account (OutgoingAccountPackets.cs) +- [x] 0x1B - Login Confirmation +- [x] 0x53 - Popup Message +- [x] 0x55 - Login Complete +- [x] 0x81 - Change Character +- [x] 0x82 - Account Login Rejected +- [x] 0x85 - Character Delete Result +- [x] 0x86 - Character List Update +- [x] 0x8C - Play Server Ack +- [x] 0xA8 - Account Login Ack (Server List) +- [x] 0xA9 - Character List (VERSION: 7.0.13.0 extended cities) +- [x] 0xB9 - Supported Features (VERSION: 6.0.14.2 extended to 4 bytes) +- [x] 0xBD - Client Version Request + +### Movement (OutgoingMovementPackets.cs) +- [x] 0x21 - Movement Rejection +- [x] 0x22 - Movement Acknowledgment +- [x] 0x97 - Move Player +- [x] 0xBF/0x26 - Speed Control +- [x] 0xF2 - Time Sync Response + +### Entity (OutgoingEntityPackets.cs) +- [x] 0x1D - Remove Entity +- [x] 0xDC - OPL Info +- [x] 0xF3 - World Entity (VERSION: 7.0.0.0 SA, 7.0.9.0 HS adds 2 bytes) + +### Mobile (OutgoingMobilePackets.cs) +- [x] 0x11 - Mobile Status (VERSION: Multiple versions 0-6 based on expansion) +- [x] 0x17 - Mobile Healthbar +- [x] 0x20 - Mobile Update +- [x] 0x2D - Mobile Attributes +- [x] 0x6E - Mobile Animation +- [x] 0x77 - Mobile Moving +- [x] 0x78 - Mobile Incoming (VERSION: 7.0.33.1 always includes hue) +- [x] 0x98 - Mobile Name +- [x] 0xA1 - Mobile Hits +- [x] 0xA2 - Mobile Mana +- [x] 0xA3 - Mobile Stamina +- [x] 0xAF - Death Animation +- [x] 0xBF/0x19 - Bonded Status +- [x] 0xE2 - New Mobile Animation + +### Item (OutgoingItemPackets.cs) +- [ ] 0x1A - World Item (pre-SA) + +### Container (OutgoingContainerPackets.cs) +- [ ] 0x24 - Display Container (VERSION: 6017 adds gump type) +- [ ] 0x25 - Container Content Update (VERSION: 6017 adds grid location) +- [ ] 0x3C - Container Content (VERSION: 6017 adds grid location per item) +- [ ] 0xBF/0x1B - New Spellbook Content (AOS) + +### Message (OutgoingMessagePackets.cs) +- [ ] 0x15 - Follow Message +- [ ] 0x1C - ASCII Message +- [ ] 0xAE - Unicode Message +- [ ] 0xB7 - Help Response +- [ ] 0xC1 - Localized Message +- [ ] 0xC2 - Prompt (outgoing) +- [ ] 0xCC - Localized Message Affix + +### Player (OutgoingPlayerPackets.cs) +- [ ] 0x23 - Drag Effect +- [ ] 0x27 - Lift Reject +- [ ] 0x2C - Death Status +- [ ] 0x38 - Pathfind Message +- [ ] 0x3A - Skills Update +- [ ] 0x5B - Current Time +- [ ] 0x65 - Weather +- [ ] 0x6D - Play Music +- [ ] 0x73 - Ping Ack +- [ ] 0x76 - Server Change +- [ ] 0x7B - Sequence +- [ ] 0x88 - Display Paperdoll +- [ ] 0x95 - Display Hue Picker +- [ ] 0xA5 - Launch Browser +- [ ] 0xA6 - Scroll Message +- [ ] 0xBC - Season Change +- [ ] 0xBF/0x19 - Stat Lock Info +- [ ] 0xC8 - Change Update Range +- [ ] 0xD1 - Logout Ack + +### Combat (OutgoingCombatPackets.cs) +- [ ] 0x2F - Swing +- [ ] 0x72 - Set War Mode +- [ ] 0xAA - Change Combatant + +### Damage (OutgoingDamagePackets.cs) +- [ ] 0x0B - Damage (VERSION: 5.0.0a, or 0xBF/0x22 for older) + +### Light (OutgoingLightPackets.cs) +- [ ] 0x4E - Personal Light Level +- [ ] 0x4F - Global Light Level + +### Effects (OutgoingEffectPackets.cs) +- [ ] 0x54 - Sound Effect +- [ ] 0x70 - Screen Effect +- [ ] 0xC0 - Hued Effect +- [ ] 0xC7 - Particle Effect + +### Target (OutgoingTargetPackets.cs) +- [ ] 0x6C - Target Request/Cancel (VERSION: HS adds 4 bytes to multi target) +- [ ] 0x99 - Multi Target Request + +### Equipment (OutgoingEquipmentPackets.cs) +- [ ] 0x2E - Equip Update +- [ ] 0xBF/0x10 - Display Equipment Info + +### Vendor (OutgoingVendorBuyPackets.cs, OutgoingVendorSellPackets.cs) +- [ ] 0x3B - End Vendor Buy +- [ ] 0x74 - Vendor Buy List +- [ ] 0x9E - Vendor Sell List + +### Map (OutgoingMapPackets.cs) +- [ ] 0xBF/0x08 - Map Change +- [ ] 0xBF/0x18 - Map Patches +- [ ] 0xC6 - Invalid Map + +### Menu (OutgoingMenuPackets.cs) +- [ ] 0x7C - Display Item List Menu + +### Secure Trade (OutgoingSecureTradePackets.cs) +- [ ] 0x6F - Secure Trade (VERSION: 7.0.45.65 new format) + +### Gumps (OutgoingGumpPackets.cs) +- [ ] 0x8B - Display Sign Gump +- [ ] 0xBF/0x04 - Close Gump + +### Party (PartyPackets.cs) +- [ ] 0xBF/0x06 - Party packets (multiple sub-types) + +### Buff Icons (BuffIconPackets.cs) +- [ ] 0xDF - Buff/Debuff System + +### Books (BookPackets.cs) +- [ ] 0x66 - Book Content +- [ ] 0x93 - Book Header (old) +- [ ] 0xD4 - Book Header (new) + +### Bulletin Boards (BulletinBoardPackets.cs) +- [ ] 0x71 - Bulletin Board Content + +### Maps (MapItemPackets.cs) +- [ ] 0x56 - Map Details +- [ ] 0x90 - Map Display +- [ ] 0xF5 - New Map Display + +### Chat (ChatPackets.cs) +- [ ] 0xB2 - Chat Message +- [ ] 0xB5 - Open Chat Window + +### Context Menus (ContextMenuSystem.cs) +- [ ] 0xBF/0x14 - Display Context Menu + +### Corpse (CorpsePackets.cs) +- [ ] 0x3C - Corpse Content + +### House (HousePackets.cs) +- [ ] House Design packets (multiple) + +### Boats (BoatPackets.cs) +- [ ] 0xF6 - Move Boat HS + +### Quest (MLQuestPackets.cs) +- [ ] Quest-related packets + +### Tracking (OutgoingArrowPackets.cs) +- [ ] 0xBA - Quest Arrow + +### Character Statue (CharacterStatuePackets.cs) +- [ ] 0xBF/0x20 - Custom House Info + +### Weapon Abilities (WeaponAbilityPackets.cs) +- [ ] 0xBF/0x21 - Clear Weapon Ability +- [ ] 0xBF/0x25 - Toggle Special Ability + +### Mahjong (MahjongPackets.cs) +- [ ] 0xDA - Mahjong game packets + +--- + +## Questions for Clarification + +### Version/Protocol Questions + +1. **Drop Request (0x08)**: The code shows `ContainerGridPacketHandler` - is this the 6017 version that adds the grid byte? What was the original format? + +2. **Container Content Update (0x25)**: I see the size varies by `ContainerGridLines`. Is it 20 bytes pre-6017 and 21 bytes post-6017? + +3. **Container Content (0x3C)**: Same question - does each item entry gain 1 byte for grid position? + +4. **Display Container (0x24)**: The code shows 7 or 9 bytes. What's the difference and which version introduced the extra 2 bytes? + +5. **Secure Trade (0x6F)**: What fields changed in 7.0.45.65 (NewSecureTrading)? + +6. **Multi Target (0x99)**: You mentioned HS adds bytes - is it 26 pre-HS and 30 post-HS? + +7. **Damage Packet**: Pre-5.0.0a clients use 0xBF/0x22, post-5.0.0a use 0x0B. Is this correct? + +### Enum/Flag Questions + +8. **ALRReason (Account Login Rejection)**: Is this a sequential enum (0-3, 254, 255)? + +9. **PMMessage (Popup Message)**: Sequential enum (0-7)? + +10. **DeleteResultType**: Sequential enum (0-5)? + +11. **Direction**: Sequential 0-7 plus 0x80 running flag - should this be documented as enum + bitflag? + +12. **Notoriety**: Sequential 0-7? + +13. **Mobile Packet Flags**: This appears to be a bitfield (Hidden=0x80, Poisoned=0x04, etc.) - can you confirm all flag values? + +14. **FeatureFlags (0xB9)**: This is a bitfield - should we document all the flag values? + +15. **CharacterListFlags (0xA9)**: Also a bitfield? + +16. **ClientFlags**: Also a bitfield? + +### Packet Structure Questions + +17. **Book packets (0x66, 0x93, 0xD4)**: These use UTF-8. Is the string format length-prefixed or null-terminated? + +18. **Speech packets (0x03, 0xAD, 0x1C, 0xAE)**: What determines ASCII vs Unicode? Is 0x03/0x1C always ASCII and 0xAD/0xAE always Unicode? + +19. **Localized Message (0xC1, 0xCC)**: The arguments field - is it Unicode LE with tab separators? + +20. **Extended Packet (0xBF)**: Some subpackets like 0x06 (Party) have further sub-types. Should we nest these or list each as separate packets? + +21. **Mobile Status (0x11)**: The version is determined by: + - Version 0 = always used when viewing OTHER mobiles (compact) + - Versions 3-6 = used when viewing SELF, based on ExpansionInfo.MobileStatusVersion + Is this correct? + +22. **Mobile Incoming (0x78)**: The equipment list - for pre-NewMobileIncoming clients, the hue field is only included if itemId has bit 0x8000 set. For NewMobileIncoming clients, hue is always included. Is this correct? + +--- + +## Schema Updates Needed + +### 1. Enum Field Support +```json +{ + "name": "reason", + "type": "enum", + "enumType": "sequential", + "size": 1, + "values": [ + { "value": 0, "name": "Invalid" }, + { "value": 1, "name": "InUse" }, + { "value": 2, "name": "Blocked" }, + { "value": 3, "name": "BadPass" }, + { "value": 254, "name": "Idle" }, + { "value": 255, "name": "BadComm" } + ] +} +``` + +### 2. Bitfield Support +```json +{ + "name": "flags", + "type": "bitfield", + "size": 1, + "flags": [ + { "bit": 0x80, "name": "Hidden" }, + { "bit": 0x40, "name": "Warmode" }, + { "bit": 0x08, "name": "Blessed" }, + { "bit": 0x04, "name": "Poisoned" }, + { "bit": 0x02, "name": "Female" } + ] +} +``` + +### 3. Packet Variants Support +```json +{ + "id": "0x11", + "name": "Mobile Status", + "variants": [ + { + "version": "0", + "name": "Compact (Other Mobile)", + "condition": "Viewing other mobile", + "size": 43, + "fields": [...] + }, + { + "version": "3", + "name": "Basic (Pre-AOS)", + "condition": "Self, Expansion < AOS", + "size": 70, + "fields": [...] + } + ] +} +``` + +--- + +## Progress Summary +- **Incoming Packets**: 66 documented (including 16 extended 0xBF subpackets) +- **Outgoing Packets**: 79 documented +- **Total**: 145 packets + +## Recently Added Files +- `incoming/extended.json` - 0xBF extended command subpackets (16 packets) +- `incoming/items.json` - Lift, Drop, Equip packets +- `incoming/player.json` - Attack, TextCommand, Skills, War mode, etc. +- `incoming/message.json` - ASCII/Unicode speech packets +- `incoming/mobile.json` - Secure trade, rename, profile +- `incoming/vendor.json` - Buy/sell responses +- `incoming/targeting.json` - Target response +- `outgoing/message.json` - ASCII/Unicode messages, localized messages +- `outgoing/player.json` - Stats, skills, weather, music, paperdoll +- `outgoing/container.json` - Container display, content, spellbook +- `outgoing/combat.json` - Swing, war mode, combatant +- `outgoing/effects.json` - Sound, particle effects, screen effects +- `outgoing/targeting.json` - Target request, multi target +- `outgoing/items.json` - World item (pre-SA) +- `outgoing/light.json` - Global/personal light levels +- `outgoing/damage.json` - Damage packets (new and old formats) diff --git a/Distribution/Data/packets/incoming/account.json b/Distribution/Data/packets/incoming/account.json new file mode 100644 index 000000000..5703ac8b7 --- /dev/null +++ b/Distribution/Data/packets/incoming/account.json @@ -0,0 +1,262 @@ +{ + "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": "packetId", "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": "nextLoginKey", "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": "packetId", "type": "byte", "size": 1, "value": "0x91", "description": "Packet identifier" }, + { "name": "authId", "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": "packetId", "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": "charSlot", "type": "int", "size": 4, "description": "Character slot index (0-based)" }, + { "name": "clientIP", "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": "packetId", "type": "byte", "size": 1, "value": "0xA0", "description": "Packet identifier" }, + { "name": "serverIndex", "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": "packetId", "type": "byte", "size": 1, "value": "0x83", "description": "Packet identifier" }, + { "name": "password", "type": "ascii", "size": 30, "description": "Account password for verification" }, + { "name": "charIndex", "type": "int", "size": 4, "description": "Character slot index to delete" }, + { "name": "clientIP", "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": "packetId", "type": "byte", "size": 1, "value": "0xEF", "description": "Packet identifier" }, + { "name": "seed", "type": "int", "size": 4, "description": "Random seed for encryption" }, + { "name": "clientMajor", "type": "int", "size": 4, "description": "Client major version" }, + { "name": "clientMinor", "type": "int", "size": 4, "description": "Client minor version" }, + { "name": "clientRevision", "type": "int", "size": 4, "description": "Client revision" }, + { "name": "clientPatch", "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's version request (0xBD). Contains the client version string.", + "direction": "incoming", + "isDynamic": true, + "size": "3 + version string length", + "fields": [ + { "name": "packetId", "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., '7.0.95.0')" } + ], + "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": "variable", + "fields": [ + { "name": "packetId", "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": "clientType", "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.", + "direction": "incoming", + "isDynamic": false, + "size": 104, + "fields": [ + { "name": "packetId", "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": "genderRace", "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": "skinHue", "type": "ushort", "size": 2, "description": "Skin color hue" }, + { "name": "hairStyle", "type": "short", "size": 2, "description": "Hair style ID" }, + { "name": "hairHue", "type": "short", "size": 2, "description": "Hair color hue" }, + { "name": "facialHairStyle", "type": "short", "size": 2, "description": "Facial hair style ID" }, + { "name": "facialHairHue", "type": "short", "size": 2, "description": "Facial hair color hue" }, + { "name": "unknown7", "type": "byte", "size": 1, "description": "Unknown" }, + { "name": "cityIndex", "type": "byte", "size": 1, "description": "Starting city index" }, + { "name": "charSlot", "type": "int", "size": 4, "description": "Character slot" }, + { "name": "clientIP", "type": "int", "size": 4, "description": "Client IP" }, + { "name": "shirtHue", "type": "short", "size": 2, "description": "Starting shirt hue" }, + { "name": "pantsHue", "type": "short", "size": 2, "description": "Starting pants hue" } + ], + "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": "packetId", "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": "genderRace", "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": "skinHue", "type": "ushort", "size": 2, "description": "Skin color hue" }, + { "name": "hairStyle", "type": "short", "size": 2, "description": "Hair style ID" }, + { "name": "hairHue", "type": "short", "size": 2, "description": "Hair color hue" }, + { "name": "facialHairStyle", "type": "short", "size": 2, "description": "Facial hair style ID" }, + { "name": "facialHairHue", "type": "short", "size": 2, "description": "Facial hair color hue" }, + { "name": "unknown7", "type": "byte", "size": 1, "description": "Unknown" }, + { "name": "cityIndex", "type": "byte", "size": 1, "description": "Starting city index" }, + { "name": "charSlot", "type": "int", "size": 4, "description": "Character slot" }, + { "name": "clientIP", "type": "int", "size": 4, "description": "Client IP" }, + { "name": "shirtHue", "type": "short", "size": 2, "description": "Starting shirt hue" }, + { "name": "pantsHue", "type": "short", "size": 2, "description": "Starting pants hue" } + ], + "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/Distribution/Data/packets/incoming/entity.json b/Distribution/Data/packets/incoming/entity.json new file mode 100644 index 000000000..75bbec2a9 --- /dev/null +++ b/Distribution/Data/packets/incoming/entity.json @@ -0,0 +1,82 @@ +{ + "category": "Entity", + "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": "packetId", "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's 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": "packetId", "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": "packetId", "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., 'ENU')" } + ], + "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 * entityCount)", + "fields": [ + { "name": "packetId", "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 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/extended.json b/Distribution/Data/packets/incoming/extended.json new file mode 100644 index 000000000..b47d74b55 --- /dev/null +++ b/Distribution/Data/packets/incoming/extended.json @@ -0,0 +1,356 @@ +{ + "category": "Extended Commands (0xBF)", + "packets": [ + { + "id": "0xBF", + "name": "Extended Command", + "description": "Wrapper packet for extended command subpackets.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "description": "Extended command ID" }, + { "name": "data", "type": "byte[]", "description": "Subcommand-specific data" } + ], + "notes": "See individual 0xBF/0xXX packets for subcommand details.", + "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x06", "description": "Party Message subcommand" }, + { + "name": "partyCommand", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Party command type", + "values": [ + { "value": 1, "name": "AddMember", "description": "Add member to party" }, + { "value": 2, "name": "RemoveMember", "description": "Remove member from party" }, + { "value": 3, "name": "PrivateMessage", "description": "Send private message to party member" }, + { "value": 4, "name": "PublicMessage", "description": "Send public message to party" }, + { "value": 6, "name": "SetCanLoot", "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/0x09", + "subId": "0x09", + "name": "Disarm Request", + "description": "Client requests to disarm opponent.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x0B", "description": "Language subcommand" }, + { "name": "language", "type": "ascii", "size": 4, "description": "Language code (e.g., 'ENU')" } + ], + "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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/0x10", + "subId": "0x10", + "name": "Query Properties", + "description": "Client queries Object Property List (tooltip) for an entity.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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", "relationship": "response", "note": "OPL Info packet" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 355 + } + }, + { + "id": "0xBF/0x1A", + "subId": "0x1A", + "name": "Stat Lock Change", + "description": "Client changes stat lock (STR/DEX/INT).", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "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": "lockValue", + "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x1C", "description": "Cast Spell subcommand" }, + { "name": "hasBook", "type": "short", "size": 2, "description": "1 if casting from book, 0 otherwise" }, + { "name": "bookSerial", "type": "uint", "size": 4, "description": "Serial of spellbook (if hasBook)", "condition": "hasBook == 1" }, + { "name": "spellId", "type": "short", "size": 2, "description": "Spell ID + 1 (1-based)" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 257 + } + }, + { + "id": "0xBF/0x2C", + "subId": "0x2C", + "name": "Bandage Target", + "description": "Client uses bandage on a target.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2C", "description": "Bandage Target subcommand" }, + { "name": "bandageSerial", "type": "uint", "size": 4, "description": "Serial of the bandage item" }, + { "name": "targetSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2D", "description": "Targeted Spell subcommand" }, + { "name": "spellId", "type": "short", "size": 2, "description": "Spell ID + 1 (1-based)" }, + { "name": "targetSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x2E", "description": "Targeted Skill Use subcommand" }, + { "name": "skillId", "type": "short", "size": 2, "description": "Skill ID" }, + { "name": "targetSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x30", "description": "Target By Resource Macro subcommand" }, + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of item" }, + { "name": "resourceType", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x32", "description": "Toggle Flying subcommand" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingExtendedCommandPackets.cs", + "line": 272 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/items.json b/Distribution/Data/packets/incoming/items.json new file mode 100644 index 000000000..cfecfddd0 --- /dev/null +++ b/Distribution/Data/packets/incoming/items.json @@ -0,0 +1,142 @@ +{ + "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": "packetId", "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": "14 (pre-6017) or 15 (6017+)", + "variants": [ + { + "version": "pre-6017", + "name": "Classic", + "size": 14, + "fields": [ + { "name": "packetId", "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 >= 6.0.1.7 (ContainerGridLines)", + "size": 15, + "fields": [ + { "name": "packetId", "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": "gridLocation", "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": "packetId", "type": "byte", "size": 1, "value": "0x13", "description": "Packet identifier" }, + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of item to equip" }, + { "name": "layer", "type": "byte", "size": 1, "description": "Equipment layer" }, + { "name": "mobileSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/message.json b/Distribution/Data/packets/incoming/message.json new file mode 100644 index 000000000..da04a00ea --- /dev/null +++ b/Distribution/Data/packets/incoming/message.json @@ -0,0 +1,97 @@ +{ + "category": "Message", + "packets": [ + { + "id": "0x03", + "name": "ASCII Speech", + "description": "Client sends ASCII-encoded speech message.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "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-null", "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 with optional keywords.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xAD", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { + "name": "type", + "type": "bitfield", + "size": 1, + "description": "Message type with possible Encoded flag", + "flags": [ + { "bit": "0x0F", "name": "MessageType", "description": "Base message type (see 0x03)" }, + { "bit": "0xC0", "name": "Encoded", "description": "If set, packet contains encoded keywords" } + ] + }, + { "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": "encodedKeywords", + "type": "conditional", + "condition": "type & 0xC0 != 0", + "fields": [ + { "name": "keywordValue", "type": "short", "size": 2, "description": "Keyword count (upper 12 bits) and first hold value (lower 4 bits)" }, + { "name": "keywords", "type": "byte[]", "description": "Packed keyword IDs" }, + { "name": "text", "type": "utf8-null", "description": "Speech text (UTF-8 when encoded)" } + ] + }, + { + "name": "unicodeText", + "type": "conditional", + "condition": "type & 0xC0 == 0", + "fields": [ + { "name": "text", "type": "unicode-be-null", "description": "Speech text (Big Endian Unicode)" } + ] + } + ], + "related": [ + { "id": "0xAE", "relationship": "response", "note": "Unicode Message sent to other clients" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMessagePackets.cs", + "line": 58 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/mobile.json b/Distribution/Data/packets/incoming/mobile.json new file mode 100644 index 000000000..4d6986c27 --- /dev/null +++ b/Distribution/Data/packets/incoming/mobile.json @@ -0,0 +1,132 @@ +{ + "category": "Mobile", + "packets": [ + { + "id": "0x6F", + "name": "Secure Trade", + "description": "Client interacts with a secure trade window.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x6F", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { + "name": "action", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Trade action type", + "values": [ + { "value": 1, "name": "Cancel", "description": "Cancel the trade" }, + { "value": 2, "name": "Check", "description": "Toggle accept checkbox" }, + { "value": 3, "name": "UpdateGold", "description": "Update virtual gold/platinum amounts" } + ] + }, + { "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the trade container" }, + { + "name": "checkData", + "type": "conditional", + "condition": "action == 2", + "fields": [ + { "name": "accepted", "type": "int", "size": 4, "description": "Non-zero if accepting trade" } + ] + }, + { + "name": "goldData", + "type": "conditional", + "condition": "action == 3", + "fields": [ + { "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", "relationship": "response", "note": "Server sends Secure Trade packet updates" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 93 + } + }, + { + "id": "0x75", + "name": "Rename Request", + "description": "Client requests to rename a mobile (pet).", + "direction": "incoming", + "isDynamic": false, + "size": 35, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x75", "description": "Packet identifier" }, + { "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of mobile to rename" }, + { "name": "newName", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x98", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "mobileSerial", "type": "uint", "size": 4, "description": "Serial of mobile to query" } + ], + "related": [ + { "id": "0x98", "relationship": "response", "note": "Server sends Mobile Name response" } + ], + "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xB8", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { + "name": "mode", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Request mode", + "values": [ + { "value": 0, "name": "Display", "description": "Request to view profile" }, + { "value": 1, "name": "Edit", "description": "Request to edit profile" } + ] + }, + { "name": "mobileSerial", "type": "uint", "size": 4, "description": "Serial of target mobile" }, + { + "name": "editData", + "type": "conditional", + "condition": "mode == 1", + "fields": [ + { "name": "padding", "type": "short", "size": 2, "description": "Unused padding" }, + { "name": "textLength", "type": "ushort", "size": 2, "description": "Length of text in characters" }, + { "name": "text", "type": "unicode-be", "description": "New profile text" } + ] + } + ], + "related": [ + { "id": "0xB8", "relationship": "response", "note": "Display Profile packet" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingMobilePackets.cs", + "line": 53 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/movement.json b/Distribution/Data/packets/incoming/movement.json new file mode 100644 index 000000000..89f47471a --- /dev/null +++ b/Distribution/Data/packets/incoming/movement.json @@ -0,0 +1,27 @@ +{ + "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": "packetId", "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": "fastwalkKey", "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/Distribution/Data/packets/incoming/player.json b/Distribution/Data/packets/incoming/player.json new file mode 100644 index 000000000..0ddf5aa19 --- /dev/null +++ b/Distribution/Data/packets/incoming/player.json @@ -0,0 +1,470 @@ +{ + "category": "Player", + "packets": [ + { + "id": "0x01", + "name": "Disconnect", + "description": "Client sends disconnect notification.", + "direction": "incoming", + "isDynamic": false, + "size": 5, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x01", "description": "Packet identifier" }, + { "name": "minusOne", "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": "packetId", "type": "byte", "size": 1, "value": "0x05", "description": "Packet identifier" }, + { "name": "targetSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x12", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { + "name": "commandType", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Type of text command", + "values": [ + { "value": "0x24", "name": "UseSkill", "description": "Use a skill by ID" }, + { "value": "0x27", "name": "CastSpellFromBook", "description": "Cast spell from spellbook" }, + { "value": "0x2F", "name": "OldScrollClick", "description": "Old scroll double-click" }, + { "value": "0x43", "name": "OpenSpellbook", "description": "Open spellbook of type" }, + { "value": "0x56", "name": "CastSpellMacro", "description": "Cast spell from macro" }, + { "value": "0x58", "name": "OpenDoor", "description": "Open door macro" }, + { "value": "0xC7", "name": "Animate", "description": "Play animation" }, + { "value": "0xF4", "name": "InvokeVirtue", "description": "Invoke virtue from macro" } + ] + }, + { "name": "command", "type": "ascii-null", "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", + "isDynamic": false, + "size": 3, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x22", "description": "Packet identifier" }, + { "name": "padding", "type": "ushort", "size": 2, "description": "Unused padding" } + ], + "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": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0x34", "description": "Packet identifier" }, + { "name": "pattern", "type": "uint", "size": 4, "value": "0xEDEDEDED", "description": "Fixed pattern" }, + { + "name": "queryType", + "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": "mobileSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x3A", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "skillIndex", "type": "short", "size": 2, "description": "Skill index to change" }, + { + "name": "lockState", + "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": "packetId", "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)" } + ], + "related": [ + { "id": "0x72", "relationship": "response", "note": "Server echoes back war mode state" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0x73", "description": "Packet identifier" }, + { "name": "sequence", "type": "byte", "size": 1, "description": "Ping sequence number" } + ], + "related": [ + { "id": "0x73", "relationship": "response", "note": "Server echoes back same sequence" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0x7D", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Menu dialog serial" }, + { "name": "menuId", "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": "itemId", "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": "packetId", "type": "byte", "size": 1, "value": "0x95", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Hue picker serial" }, + { "name": "itemId", "type": "short", "size": 2, "description": "Item ID (unused)" }, + { "name": "hue", "type": "short", "size": 2, "description": "Selected hue (masked with 0x3FFF)" } + ], + "related": [ + { "id": "0x95", "relationship": "request", "note": "Display Hue Picker packet" } + ], + "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "promptId", "type": "int", "size": 4, "description": "Prompt ID" }, + { "name": "type", "type": "int", "size": 4, "description": "Response type: 0 = cancel, other = submit" }, + { "name": "text", "type": "ascii-null", "description": "Response text (max 128 chars)" } + ], + "related": [ + { "id": "0xC2", "relationship": "request", "note": "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": "packetId", "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": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0xA7", "description": "Packet identifier" }, + { "name": "lastTip", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "promptId", "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., 'ENU')" }, + { "name": "text", "type": "unicode-le-null", "description": "Response text (max 128 chars)" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0xC8", "description": "Packet identifier" }, + { "name": "range", "type": "byte", "size": 1, "description": "Requested update range (ignored)" } + ], + "related": [ + { "id": "0xC8", "relationship": "response", "note": "Server sends back fixed range (18)" } + ], + "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0xD1", "description": "Packet identifier" }, + { "name": "unknown", "type": "byte", "size": 1, "description": "Unknown (typically 0x01)" } + ], + "related": [ + { "id": "0xD1", "relationship": "response", "note": "Server sends Logout Ack" } + ], + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 326 + } + }, + { + "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xD7", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "entitySerial", "type": "uint", "size": 4, "description": "Serial of target entity" }, + { "name": "subCommand", "type": "ushort", "size": 2, "description": "Encoded command ID" }, + { "name": "data", "type": "byte[]", "description": "Subcommand-specific data" } + ], + "notes": "See encoded.json for subpacket definitions", + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingPlayerPackets.cs", + "line": 457 + } + }, + { + "id": "0xF4", + "name": "Crash Report", + "description": "Client sends crash/error report.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xF4", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "clientMajor", "type": "byte", "size": 1, "description": "Client major version" }, + { "name": "clientMinor", "type": "byte", "size": 1, "description": "Client minor version" }, + { "name": "clientRev", "type": "byte", "size": 1, "description": "Client revision" }, + { "name": "clientPat", "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": "accountName", "type": "ascii", "size": 32, "description": "Account name" }, + { "name": "characterName", "type": "ascii", "size": 32, "description": "Character name" }, + { "name": "ipAddress", "type": "ascii", "size": 15, "description": "Client IP address" }, + { "name": "unknown1", "type": "int", "size": 4, "description": "Unknown" }, + { "name": "exceptionCode", "type": "int", "size": 4, "description": "Exception code" }, + { "name": "processName", "type": "ascii", "size": 100, "description": "Process name" }, + { "name": "reportText", "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": "stackCount", "type": "byte", "size": 1, "description": "Number of stack trace entries" }, + { + "name": "stackAddresses", + "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 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/targeting.json b/Distribution/Data/packets/incoming/targeting.json new file mode 100644 index 000000000..c0947e342 --- /dev/null +++ b/Distribution/Data/packets/incoming/targeting.json @@ -0,0 +1,55 @@ +{ + "category": "Targeting", + "packets": [ + { + "id": "0x6C", + "name": "Target Response", + "description": "Client responds to a target cursor request.", + "direction": "incoming", + "isDynamic": false, + "size": 19, + "fields": [ + { "name": "packetId", "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": "targetId", "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": "targetSerial", "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)" } + ], + "related": [ + { "id": "0x6C", "relationship": "request", "note": "Target Request packet that initiated this" } + ], + "notes": "If x == -1 && y == -1 && serial is invalid, user pressed Escape to cancel targeting.", + "source": { + "file": "Projects/UOContent/Network/Packets/IncomingTargetingPackets.cs", + "line": 28 + } + } + ] +} diff --git a/Distribution/Data/packets/incoming/vendor.json b/Distribution/Data/packets/incoming/vendor.json new file mode 100644 index 000000000..f9a5b7541 --- /dev/null +++ b/Distribution/Data/packets/incoming/vendor.json @@ -0,0 +1,70 @@ +{ + "category": "Vendor", + "packets": [ + { + "id": "0x3B", + "name": "Vendor Buy Reply", + "description": "Client confirms items to purchase from a vendor.", + "direction": "incoming", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x3B", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "vendorSerial", "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": "itemSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x9F", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "vendorSerial", "type": "uint", "size": 4, "description": "Serial of the vendor" }, + { "name": "itemCount", "type": "ushort", "size": 2, "description": "Number of items to sell" }, + { + "name": "items", + "type": "loop", + "loop": { + "countField": "itemCount", + "fields": [ + { "name": "itemSerial", "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/Distribution/Data/packets/outgoing/account.json b/Distribution/Data/packets/outgoing/account.json new file mode 100644 index 000000000..daa3ab72c --- /dev/null +++ b/Distribution/Data/packets/outgoing/account.json @@ -0,0 +1,320 @@ +{ + "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": "packetId", "type": "byte", "size": 1, "value": "0x82", "description": "Packet identifier" }, + { "name": "reason", "type": "byte", "size": 1, "description": "Rejection reason: 0=Invalid, 1=InUse, 2=Blocked, 3=BadPass, 254=Idle, 255=BadComm" } + ], + "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 * serverCount)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA8", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "systemInfoFlag", "type": "byte", "size": 1, "value": "0x5D", "description": "System info flag" }, + { "name": "serverCount", "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": "fullPercent", "type": "byte", "size": 1, "description": "Server load percentage" }, + { "name": "timezone", "type": "sbyte", "size": 1, "description": "Server timezone offset" }, + { "name": "ipAddress", "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": "packetId", "type": "byte", "size": 1, "value": "0x8C", "description": "Packet identifier" }, + { "name": "ipAddress", "type": "uint", "size": 4, "description": "Game server IP address (little-endian)" }, + { "name": "port", "type": "short", "size": 2, "description": "Game server port" }, + { "name": "authId", "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.", + "direction": "outgoing", + "isDynamic": true, + "size": "variable (client version dependent)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA9", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "charCount", "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" } + ] + } + }, + { "name": "cityCount", "type": "byte", "size": 1, "description": "Number of starting cities" }, + { + "name": "cities", + "type": "array", + "description": "Starting city entries", + "loop": { + "countField": "cityCount", + "fields": [ + { "name": "index", "type": "byte", "size": 1, "description": "City index" }, + { "name": "cityName", "type": "ascii", "size": 31, "description": "City name (32 for 7.0.13.0+)" }, + { "name": "buildingName", "type": "ascii", "size": 31, "description": "Building name (32 for 7.0.13.0+)" }, + { "name": "x", "type": "int", "size": 4, "description": "X coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }, + { "name": "y", "type": "int", "size": 4, "description": "Y coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }, + { "name": "z", "type": "int", "size": 4, "description": "Z coordinate (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }, + { "name": "mapId", "type": "int", "size": 4, "description": "Map ID (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }, + { "name": "cliloc", "type": "int", "size": 4, "description": "Description cliloc (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" }, + { "name": "unknown", "type": "int", "size": 4, "description": "Unknown (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" } + ] + } + }, + { "name": "flags", "type": "int", "size": 4, "description": "Character list flags (slot limits, features)" }, + { "name": "lastCharSlot", "type": "short", "size": 2, "description": "Last played character slot (7.0.13.0+ only)", "condition": "client >= 7.0.13.0" } + ], + "clientVersion": { + "feature": "NewCharacterList", + "notes": "Clients 7.0.13.0+ use extended city format with coordinates" + }, + "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's mobile serial and initial position.", + "direction": "outgoing", + "isDynamic": false, + "size": 37, + "fields": [ + { "name": "packetId", "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": "mapWidth", "type": "short", "size": 2, "description": "Map width in tiles" }, + { "name": "mapHeight", "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": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0xBD", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "0x0003", "description": "Packet length" } + ], + "related": [ + { "id": "0xBD", "relationship": "response", "note": "Client responds with version string" } + ], + "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.", + "direction": "outgoing", + "isDynamic": false, + "size": "3 or 5 (client version dependent)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xB9", "description": "Packet identifier" }, + { "name": "features", "type": "ushort/uint", "size": "2 or 4", "description": "Feature flags bitmask. Extended (4 bytes) for newer clients." } + ], + "clientVersion": { + "feature": "ExtendedSupportedFeatures", + "notes": "Clients with ExtendedSupportedFeatures use 4-byte flags instead of 2-byte" + }, + "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": "packetId", "type": "byte", "size": 1, "value": "0x85", "description": "Packet identifier" }, + { "name": "result", "type": "byte", "size": 1, "description": "Result: 0=PasswordInvalid, 1=CharNotExist, 2=CharBeingPlayed, 3=CharTooYoung, 4=CharQueued, 5=BadRequest" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0x53", "description": "Packet identifier" }, + { "name": "messageId", "type": "byte", "size": 1, "description": "Message ID: 1=CharNoExist, 2=CharExists, 5=CharInWorld, 6=LoginSyncError, 7=IdleWarning" } + ], + "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 * charCount)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x81", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "charCount", "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 * charCount)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x86", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "charCount", "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 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/combat.json b/Distribution/Data/packets/outgoing/combat.json new file mode 100644 index 000000000..6f5662934 --- /dev/null +++ b/Distribution/Data/packets/outgoing/combat.json @@ -0,0 +1,61 @@ +{ + "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": "packetId", "type": "byte", "size": 1, "value": "0x2F", "description": "Packet identifier" }, + { "name": "unknown", "type": "byte", "size": 1, "value": "0x00", "description": "Unknown" }, + { "name": "attackerSerial", "type": "uint", "size": 4, "description": "Serial of attacker" }, + { "name": "defenderSerial", "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's war/peace mode state.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { "name": "packetId", "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" } + ], + "related": [ + { "id": "0x72", "relationship": "request", "note": "Set War Mode from client" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0xAA", "description": "Packet identifier" }, + { "name": "combatantSerial", "type": "uint", "size": 4, "description": "Serial of current combatant (0 = none)" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingCombatPackets.cs", + "line": 43 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/container.json b/Distribution/Data/packets/outgoing/container.json new file mode 100644 index 000000000..f4b0c135f --- /dev/null +++ b/Distribution/Data/packets/outgoing/container.json @@ -0,0 +1,161 @@ +{ + "category": "Container", + "packets": [ + { + "id": "0x24", + "name": "Display Container", + "description": "Opens a container gump on the client.", + "direction": "outgoing", + "isDynamic": false, + "size": "7 (pre-HS) or 9 (HS+)", + "variants": [ + { + "version": "pre-HighSeas", + "name": "Classic", + "size": 7, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x24", "description": "Packet identifier" }, + { "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the container" }, + { "name": "gumpId", "type": "ushort", "size": 2, "description": "Gump graphic ID" } + ] + }, + { + "version": "HighSeas+", + "name": "High Seas Extended", + "condition": "Client version >= 7.0.9.0 (HighSeas)", + "size": 9, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x24", "description": "Packet identifier" }, + { "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of the container" }, + { "name": "gumpId", "type": "ushort", "size": 2, "description": "Gump graphic ID" }, + { "name": "containerType", "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": "20 (pre-6017) or 21 (6017+)", + "variants": [ + { + "version": "pre-6017", + "name": "Classic", + "size": 20, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x25", "description": "Packet identifier" }, + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" }, + { "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" }, + { "name": "itemIdOffset", "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": "containerSerial", "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 >= 6.0.1.7 (ContainerGridLines)", + "size": 21, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x25", "description": "Packet identifier" }, + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" }, + { "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" }, + { "name": "itemIdOffset", "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": "gridLocation", "type": "byte", "size": 1, "description": "Grid slot position" }, + { "name": "containerSerial", "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 Content", + "description": "Sends full contents of a container.", + "direction": "outgoing", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x3C", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "itemCount", "type": "ushort", "size": 2, "description": "Number of items" }, + { + "name": "items", + "type": "loop", + "loop": { + "countField": "itemCount", + "itemSize": "19 (pre-6017) or 20 (6017+)", + "fields": [ + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Serial of the item" }, + { "name": "itemId", "type": "ushort", "size": 2, "description": "Item graphic ID" }, + { "name": "itemIdOffset", "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": "gridLocation", "type": "byte", "size": 1, "description": "Grid slot (6017+ only)", "condition": "ContainerGridLines" }, + { "name": "containerSerial", "type": "uint", "size": 4, "description": "Serial of parent container" }, + { "name": "hue", "type": "ushort", "size": 2, "description": "Item hue" } + ] + } + } + ], + "clientVersion": { + "feature": "ContainerGridLines adds gridLocation byte per item" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 169 + } + }, + { + "id": "0xBF/0x1B", + "name": "New Spellbook Content", + "description": "Sends spellbook contents using AOS format.", + "direction": "outgoing", + "isDynamic": false, + "size": 23, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "23", "description": "Packet length" }, + { "name": "subCommand", "type": "short", "size": 2, "value": "0x1B", "description": "Subcommand (New Spellbook Content)" }, + { "name": "command", "type": "short", "size": 2, "value": "0x01", "description": "Command (always 1)" }, + { "name": "bookSerial", "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": "spellBits", "type": "ulong", "size": 8, "description": "64-bit mask of known spells (Little Endian)" } + ], + "clientVersion": { + "min": "5.0.0a", + "feature": "NewSpellbook" + }, + "notes": "Used when Core.AOS && ns.NewSpellbook. Otherwise, old 0x3C format is used.", + "source": { + "file": "Projects/Server/Network/Packets/OutgoingContainerPackets.cs", + "line": 46 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/damage.json b/Distribution/Data/packets/outgoing/damage.json new file mode 100644 index 000000000..788c5b627 --- /dev/null +++ b/Distribution/Data/packets/outgoing/damage.json @@ -0,0 +1,52 @@ +{ + "category": "Damage", + "packets": [ + { + "id": "0x0B", + "name": "Damage", + "description": "Shows damage dealt to a mobile (client 5.0.0a+).", + "direction": "outgoing", + "isDynamic": false, + "size": 7, + "fields": [ + { "name": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "11", "description": "Packet length" }, + { "name": "subCommand", "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/Distribution/Data/packets/outgoing/effects.json b/Distribution/Data/packets/outgoing/effects.json new file mode 100644 index 000000000..552c040e5 --- /dev/null +++ b/Distribution/Data/packets/outgoing/effects.json @@ -0,0 +1,142 @@ +{ + "category": "Effects", + "packets": [ + { + "id": "0x54", + "name": "Sound Effect", + "description": "Plays a sound effect at a location.", + "direction": "outgoing", + "isDynamic": false, + "size": 12, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x54", "description": "Packet identifier" }, + { "name": "flags", "type": "byte", "size": 1, "value": "0x01", "description": "Sound flags" }, + { "name": "soundId", "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": "packetId", "type": "byte", "size": 1, "value": "0x70", "description": "Packet identifier" }, + { "name": "effectType", "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": "FadeOut", "description": "Fade screen to black" }, + { "value": 1, "name": "FadeIn", "description": "Fade screen from black" }, + { "value": 2, "name": "LightFlash", "description": "Light flash effect" }, + { "value": 3, "name": "FadeInOut", "description": "Fade out then in" }, + { "value": 4, "name": "DarkenScreen", "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": "packetId", "type": "byte", "size": 1, "value": "0xC0", "description": "Packet identifier" }, + { + "name": "effectType", + "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": "FixedXYZ", "description": "Effect at fixed location" }, + { "value": 3, "name": "FixedFrom", "description": "Effect attached to source" } + ] + }, + { "name": "sourceSerial", "type": "uint", "size": 4, "description": "Serial of source entity" }, + { "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" }, + { "name": "itemId", "type": "short", "size": 2, "description": "Effect graphic ID" }, + { "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" }, + { "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" }, + { "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" }, + { "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" }, + { "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" }, + { "name": "dstZ", "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": "fixedDirection", "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": "renderMode", "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": "packetId", "type": "byte", "size": 1, "value": "0xC7", "description": "Packet identifier" }, + { "name": "effectType", "type": "byte", "size": 1, "description": "Effect type (see 0xC0)" }, + { "name": "sourceSerial", "type": "uint", "size": 4, "description": "Serial of source entity" }, + { "name": "targetSerial", "type": "uint", "size": 4, "description": "Serial of target entity" }, + { "name": "itemId", "type": "short", "size": 2, "description": "Effect graphic ID" }, + { "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" }, + { "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" }, + { "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" }, + { "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" }, + { "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" }, + { "name": "dstZ", "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": "fixedDirection", "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": "renderMode", "type": "int", "size": 4, "description": "Render mode" }, + { "name": "effect", "type": "short", "size": 2, "description": "Particle effect ID" }, + { "name": "explodeEffect", "type": "short", "size": 2, "description": "Explosion effect ID" }, + { "name": "explodeSound", "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/Distribution/Data/packets/outgoing/entity.json b/Distribution/Data/packets/outgoing/entity.json new file mode 100644 index 000000000..d63865b1c --- /dev/null +++ b/Distribution/Data/packets/outgoing/entity.json @@ -0,0 +1,71 @@ +{ + "category": "Entity", + "packets": [ + { + "id": "0x1D", + "name": "Remove Entity", + "description": "Removes an entity (item, mobile, or multi) from the client's view.", + "direction": "outgoing", + "isDynamic": false, + "size": 5, + "fields": [ + { "name": "packetId", "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's Object Property List hash. Client compares hash to cached version and requests full OPL if different.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { "name": "packetId", "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" } + ], + "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 item/mobile-specific packets for Stygian Abyss+ clients.", + "direction": "outgoing", + "isDynamic": false, + "size": "24 (pre-HS) or 26 (HS+)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xF3", "description": "Packet identifier" }, + { "name": "command", "type": "short", "size": 2, "value": "0x0001", "description": "Command (always 1)" }, + { "name": "entityType", "type": "byte", "size": 1, "description": "Entity type: 0=Item, 1=Mobile, 2=Multi" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Entity serial" }, + { "name": "graphicId", "type": "ushort", "size": 2, "description": "Graphic/Body ID" }, + { "name": "direction", "type": "byte", "size": 1, "description": "Direction (mobiles) or 0" }, + { "name": "amountMin", "type": "short", "size": 2, "description": "Minimum amount (items) or 1" }, + { "name": "amountMax", "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, "description": "Unknown (HS+ only)", "condition": "HighSeas" } + ], + "clientVersion": { + "min": "7.0.9.0", + "feature": "StygianAbyss" + }, + "source": { + "file": "Projects/Server/Network/Packets/OutgoingEntityPackets.cs", + "line": 88 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/items.json b/Distribution/Data/packets/outgoing/items.json new file mode 100644 index 000000000..311e7eee3 --- /dev/null +++ b/Distribution/Data/packets/outgoing/items.json @@ -0,0 +1,35 @@ +{ + "category": "Items", + "packets": [ + { + "id": "0x1A", + "name": "World Item", + "description": "Displays an item in the world (pre-Stygian Abyss clients).", + "direction": "outgoing", + "isDynamic": true, + "size": "Dynamic (14-20 bytes)", + "fields": [ + { "name": "packetId", "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": "itemId", "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 & 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 & 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 & 0x8000" }, + { "name": "flags", "type": "byte", "size": 1, "description": "Packet flags (if y bit 14 set)", "condition": "y & 0x4000" } + ], + "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 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/light.json b/Distribution/Data/packets/outgoing/light.json new file mode 100644 index 000000000..6df86290b --- /dev/null +++ b/Distribution/Data/packets/outgoing/light.json @@ -0,0 +1,38 @@ +{ + "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": "packetId", "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": "packetId", "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/Distribution/Data/packets/outgoing/message.json b/Distribution/Data/packets/outgoing/message.json new file mode 100644 index 000000000..4c953605e --- /dev/null +++ b/Distribution/Data/packets/outgoing/message.json @@ -0,0 +1,198 @@ +{ + "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": "packetId", "type": "byte", "size": 1, "value": "0x15", "description": "Packet identifier" }, + { "name": "followerSerial", "type": "uint", "size": 4, "description": "Serial of the follower" }, + { "name": "targetSerial", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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-null", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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., 'ENU')" }, + { "name": "name", "type": "ascii", "size": 30, "description": "Speaker name" }, + { "name": "text", "type": "unicode-be-null", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "unicode-be-null", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "clilocNumber", "type": "int", "size": 4, "description": "Cliloc entry number" }, + { "name": "name", "type": "ascii", "size": 30, "description": "Speaker name" }, + { "name": "arguments", "type": "unicode-le-null", "description": "Tab-separated arguments for cliloc" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 55 + } + }, + { + "id": "0xC2", + "name": "Prompt", + "description": "Server requests text input from client.", + "direction": "outgoing", + "isDynamic": false, + "size": 21, + "fields": [ + { "name": "packetId", "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": "promptId", "type": "uint", "size": 4, "description": "Prompt ID (same as serial)" }, + { "name": "padding", "type": "byte[]", "size": 10, "description": "Unused padding (zeros)" } + ], + "related": [ + { "id": "0x9A", "relationship": "response", "note": "ASCII Prompt Response" }, + { "id": "0xC2", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "clilocNumber", "type": "int", "size": 4, "description": "Cliloc entry number" }, + { + "name": "affixType", + "type": "bitfield", + "size": 1, + "description": "How to apply the affix", + "flags": [ + { "bit": "0x00", "name": "Append", "description": "Append affix to end" }, + { "bit": "0x01", "name": "Prepend", "description": "Prepend affix to start" }, + { "bit": "0x02", "name": "System", "description": "System message style" } + ] + }, + { "name": "name", "type": "ascii", "size": 30, "description": "Speaker name" }, + { "name": "affix", "type": "ascii-null", "description": "Text to prepend/append" }, + { "name": "arguments", "type": "unicode-be-null", "description": "Tab-separated arguments for cliloc" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMessagePackets.cs", + "line": 112 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/mobile.json b/Distribution/Data/packets/outgoing/mobile.json new file mode 100644 index 000000000..f75f4222c --- /dev/null +++ b/Distribution/Data/packets/outgoing/mobile.json @@ -0,0 +1,339 @@ +{ + "category": "Mobile", + "packets": [ + { + "id": "0x11", + "name": "Mobile Status", + "description": "Detailed status information for a mobile. Length and content varies based on client version and whether viewing self or others.", + "direction": "outgoing", + "isDynamic": true, + "size": "43-121 bytes (version dependent)", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x11", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" }, + { "name": "name", "type": "ascii", "size": 30, "description": "Mobile name" }, + { "name": "hitsMax", "type": "short", "size": 2, "description": "Maximum hits (normalized to 100 for non-self)" }, + { "name": "hits", "type": "short", "size": 2, "description": "Current hits" }, + { "name": "canBeRenamed", "type": "bool", "size": 1, "description": "Whether the mobile can be renamed by viewer" }, + { "name": "version", "type": "byte", "size": 1, "description": "Status version: 0=compact, 3=basic, 4=AOS, 5=ML, 6=HS" }, + { "name": "female", "type": "bool", "size": 1, "description": "Gender flag (version 1+)", "condition": "version >= 1" }, + { "name": "str", "type": "short", "size": 2, "description": "Strength", "condition": "version >= 1" }, + { "name": "dex", "type": "short", "size": 2, "description": "Dexterity", "condition": "version >= 1" }, + { "name": "int", "type": "short", "size": 2, "description": "Intelligence", "condition": "version >= 1" }, + { "name": "stam", "type": "short", "size": 2, "description": "Current stamina", "condition": "version >= 1" }, + { "name": "stamMax", "type": "short", "size": 2, "description": "Maximum stamina", "condition": "version >= 1" }, + { "name": "mana", "type": "short", "size": 2, "description": "Current mana", "condition": "version >= 1" }, + { "name": "manaMax", "type": "short", "size": 2, "description": "Maximum mana", "condition": "version >= 1" }, + { "name": "gold", "type": "int", "size": 4, "description": "Total gold", "condition": "version >= 1" }, + { "name": "armorRating", "type": "short", "size": 2, "description": "Armor rating (physical resist in AOS+)", "condition": "version >= 1" }, + { "name": "weight", "type": "short", "size": 2, "description": "Current weight", "condition": "version >= 1" }, + { "name": "maxWeight", "type": "short", "size": 2, "description": "Maximum weight", "condition": "version >= 5" }, + { "name": "race", "type": "byte", "size": 1, "description": "Race ID + 1 (0 = no race)", "condition": "version >= 5" }, + { "name": "statCap", "type": "short", "size": 2, "description": "Stat cap", "condition": "version >= 1" }, + { "name": "followers", "type": "byte", "size": 1, "description": "Current followers", "condition": "version >= 1" }, + { "name": "followersMax", "type": "byte", "size": 1, "description": "Maximum followers", "condition": "version >= 1" }, + { "name": "fireResist", "type": "short", "size": 2, "description": "Fire resistance", "condition": "version >= 4" }, + { "name": "coldResist", "type": "short", "size": 2, "description": "Cold resistance", "condition": "version >= 4" }, + { "name": "poisonResist", "type": "short", "size": 2, "description": "Poison resistance", "condition": "version >= 4" }, + { "name": "energyResist", "type": "short", "size": 2, "description": "Energy resistance", "condition": "version >= 4" }, + { "name": "luck", "type": "short", "size": 2, "description": "Luck", "condition": "version >= 4" }, + { "name": "damageMin", "type": "short", "size": 2, "description": "Minimum weapon damage", "condition": "version >= 4" }, + { "name": "damageMax", "type": "short", "size": 2, "description": "Maximum weapon damage", "condition": "version >= 4" }, + { "name": "tithingPoints", "type": "int", "size": 4, "description": "Tithing points", "condition": "version >= 4" }, + { "name": "aosStatus", "type": "short[15]", "size": 30, "description": "Extended AOS status values", "condition": "version >= 6" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMobilePackets.cs", + "line": 497 + } + }, + { + "id": "0x20", + "name": "Mobile Update", + "description": "Updates a mobile's basic display information (body, hue, position, flags).", + "direction": "outgoing", + "isDynamic": false, + "size": 19, + "fields": [ + { "name": "packetId", "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": "packetId", "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": "byte", "size": 1, "description": "Notoriety (0=Innocent, 1=Friend, 2=Gray, 3=Criminal, 4=Enemy, 5=Murderer, 6=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 + (equipment count * 7-9 bytes)", + "fields": [ + { "name": "packetId", "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": "byte", "size": 1, "description": "Notoriety flag" }, + { + "name": "equipment", + "type": "array", + "description": "Equipped items (terminated by 0x00000000)", + "loop": { + "countField": "variable (until terminator)", + "fields": [ + { "name": "itemSerial", "type": "uint", "size": 4, "description": "Item serial (0 = end of list)" }, + { "name": "itemId", "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's hit points. Can be normalized to 0-100 scale for non-self mobiles.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA1", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" }, + { "name": "hitsMax", "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's mana points.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA2", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" }, + { "name": "manaMax", "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's stamina points.", + "direction": "outgoing", + "isDynamic": false, + "size": 9, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA3", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" }, + { "name": "stamMax", "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": "packetId", "type": "byte", "size": 1, "value": "0x2D", "description": "Packet identifier" }, + { "name": "serial", "type": "uint", "size": 4, "description": "Mobile serial" }, + { "name": "hitsMax", "type": "short", "size": 2, "description": "Maximum hits" }, + { "name": "hits", "type": "short", "size": 2, "description": "Current hits" }, + { "name": "manaMax", "type": "short", "size": 2, "description": "Maximum mana" }, + { "name": "mana", "type": "short", "size": 2, "description": "Current mana" }, + { "name": "stamMax", "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's name in response to a name request.", + "direction": "outgoing", + "isDynamic": false, + "size": 37, + "fields": [ + { "name": "packetId", "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": "packetId", "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": "frameCount", "type": "short", "size": 2, "description": "Number of frames" }, + { "name": "repeatCount", "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": "packetId", "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": "frameCount", "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's healthbar status (poison level, yellow bar for invulnerability).", + "direction": "outgoing", + "isDynamic": false, + "size": 12, + "fields": [ + { "name": "packetId", "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": "showBar", "type": "short", "size": 2, "value": "0x0001", "description": "Show bar (always 1)" }, + { "name": "healthbarType", "type": "short", "size": 2, "description": "Healthbar type: 1=Poison, 2=Yellow" }, + { "name": "level", "type": "byte", "size": 1, "description": "Level (0=off, 1-4 for poison levels, 1=on for yellow)" } + ], + "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": "packetId", "type": "byte", "size": 1, "value": "0xAF", "description": "Packet identifier" }, + { "name": "killedSerial", "type": "uint", "size": 4, "description": "Serial of the killed mobile" }, + { "name": "corpseSerial", "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": "0x0019", + "name": "Bonded Status", + "description": "Indicates whether a mobile (pet) is bonded to its owner.", + "direction": "outgoing", + "isDynamic": false, + "size": 11, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "0x000B", "description": "Packet length (11)" }, + { "name": "subCommand", "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 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/movement.json b/Distribution/Data/packets/outgoing/movement.json new file mode 100644 index 000000000..60616f215 --- /dev/null +++ b/Distribution/Data/packets/outgoing/movement.json @@ -0,0 +1,101 @@ +{ + "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": "packetId", "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's current notoriety for display purposes.", + "direction": "outgoing", + "isDynamic": false, + "size": 3, + "fields": [ + { "name": "packetId", "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": "byte", "size": 1, "description": "Player's current notoriety flag (0=Innocent, 1=Friend, 2=Gray/Attackable, 3=Criminal, 4=Enemy, 5=Murderer, 6=Invulnerable)" } + ], + "related": [ + { "id": "0x02", "relationship": "request", "note": "The movement request that was accepted" } + ], + "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": "packetId", "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": "0x0026", + "name": "Speed Control", + "description": "Controls the player's movement speed. Used for mount speed changes, walk/run restrictions, etc.", + "direction": "outgoing", + "isDynamic": false, + "size": 6, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "0x0006", "description": "Packet length" }, + { "name": "subCommand", "type": "ushort", "size": 2, "value": "0x0026", "description": "Sub-command for speed control" }, + { "name": "speedSetting", "type": "byte", "size": 1, "description": "Speed setting: 0=Disable (normal), 1=Mount speed, 2=Walk 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": "packetId", "type": "byte", "size": 1, "value": "0xF2", "description": "Packet identifier" }, + { "name": "tickCount1", "type": "long", "size": 8, "description": "Server tick count" }, + { "name": "tickCount2", "type": "long", "size": 8, "description": "Server tick count" }, + { "name": "tickCount3", "type": "long", "size": 8, "description": "Server tick count" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingMovementPackets.cs", + "line": 63 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/player.json b/Distribution/Data/packets/outgoing/player.json new file mode 100644 index 000000000..0b84a99d6 --- /dev/null +++ b/Distribution/Data/packets/outgoing/player.json @@ -0,0 +1,482 @@ +{ + "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": "packetId", "type": "byte", "size": 1, "value": "0x23", "description": "Packet identifier" }, + { "name": "itemId", "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": "srcSerial", "type": "uint", "size": 4, "description": "Source entity serial" }, + { "name": "srcX", "type": "short", "size": 2, "description": "Source X coordinate" }, + { "name": "srcY", "type": "short", "size": 2, "description": "Source Y coordinate" }, + { "name": "srcZ", "type": "sbyte", "size": 1, "description": "Source Z coordinate" }, + { "name": "dstSerial", "type": "uint", "size": 4, "description": "Destination entity serial" }, + { "name": "dstX", "type": "short", "size": 2, "description": "Destination X coordinate" }, + { "name": "dstY", "type": "short", "size": 2, "description": "Destination Y coordinate" }, + { "name": "dstZ", "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": "packetId", "type": "byte", "size": 1, "value": "0x27", "description": "Packet identifier" }, + { + "name": "reason", + "type": "enum", + "enumType": "sequential", + "size": 1, + "description": "Rejection reason", + "values": [ + { "value": 0, "name": "CannotLift", "description": "You cannot pick that up" }, + { "value": 1, "name": "OutOfRange", "description": "That is out of range" }, + { "value": 2, "name": "OutOfSight", "description": "That is out of sight" }, + { "value": 3, "name": "TryToSteal", "description": "That does not belong to you" }, + { "value": 4, "name": "AreHolding", "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": "packetId", "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": "packetId", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "FullNoCaps", "description": "Full list without caps" }, + { "value": "0x02", "name": "FullWithCaps", "description": "Full list with skill caps" }, + { "value": "0xDF", "name": "SingleWithCaps", "description": "Single skill update with cap" }, + { "value": "0xFF", "name": "SingleNoCaps", "description": "Single skill update" } + ] + }, + { + "name": "skills", + "type": "loop", + "loop": { + "until": "skillId == 0", + "fields": [ + { "name": "skillId", "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)" } + ] + } + } + ], + "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": "packetId", "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": "packetId", "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": "StormBrewing", "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": "packetId", "type": "byte", "size": 1, "value": "0x6D", "description": "Packet identifier" }, + { "name": "musicId", "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": "packetId", "type": "byte", "size": 1, "value": "0x73", "description": "Packet identifier" }, + { "name": "sequence", "type": "byte", "size": 1, "description": "Ping sequence (echoed from request)" } + ], + "related": [ + { "id": "0x73", "relationship": "request", "note": "Ping Request from client" } + ], + "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": "packetId", "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": "mapWidth", "type": "short", "size": 2, "description": "Map width" }, + { "name": "mapHeight", "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": "packetId", "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": "packetId", "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": "0x01", "name": "Warmode", "description": "Mobile is in war mode" }, + { "bit": "0x02", "name": "CanLift", "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": "packetId", "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": "itemId", "type": "short", "size": 2, "description": "Item graphic to preview hue on" } + ], + "related": [ + { "id": "0x95", "relationship": "response", "note": "Hue Picker Response from client" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 338 + } + }, + { + "id": "0xA5", + "name": "Launch Browser", + "description": "Opens a URL in client's web browser.", + "direction": "outgoing", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0xA5", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "description": "Packet length" }, + { "name": "url", "type": "ascii-null", "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": "Dynamic", + "fields": [ + { "name": "packetId", "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": "tipNumber", "type": "int", "size": 4, "description": "Tip/message number" }, + { "name": "textLength", "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's profile.", + "direction": "outgoing", + "isDynamic": true, + "size": "Dynamic", + "fields": [ + { "name": "packetId", "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-null", "description": "Profile header" }, + { "name": "footer", "type": "unicode-be-null", "description": "Profile footer" }, + { "name": "body", "type": "unicode-be-null", "description": "Profile body text" } + ], + "related": [ + { "id": "0xB8", "relationship": "request", "note": "Profile Request from client" } + ], + "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": "packetId", "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": "playSound", "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": "packetId", "type": "byte", "size": 1, "value": "0xBF", "description": "Packet identifier" }, + { "name": "length", "type": "ushort", "size": 2, "value": "12", "description": "Packet length" }, + { "name": "subCommand", "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": "lockBits", + "type": "bitfield", + "size": 1, + "description": "Packed lock states", + "flags": [ + { "bit": "0x30", "name": "StrLock", "description": "Strength lock (bits 4-5)" }, + { "bit": "0x0C", "name": "DexLock", "description": "Dexterity lock (bits 2-3)" }, + { "bit": "0x03", "name": "IntLock", "description": "Intelligence lock (bits 0-1)" } + ], + "notes": "Each lock is 2 bits: 0=Up, 1=Down, 2=Locked" + } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 36 + } + }, + { + "id": "0xC8", + "name": "Change Update Range", + "description": "Sets the client's update range.", + "direction": "outgoing", + "isDynamic": false, + "size": 2, + "fields": [ + { "name": "packetId", "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": "packetId", "type": "byte", "size": 1, "value": "0xD1", "description": "Packet identifier" }, + { "name": "ack", "type": "byte", "size": 1, "value": "0x01", "description": "Acknowledgment (1 = OK)" } + ], + "related": [ + { "id": "0xD1", "relationship": "request", "note": "Logout Request from client" } + ], + "source": { + "file": "Projects/Server/Network/Packets/OutgoingPlayerPackets.cs", + "line": 94 + } + } + ] +} diff --git a/Distribution/Data/packets/outgoing/targeting.json b/Distribution/Data/packets/outgoing/targeting.json new file mode 100644 index 000000000..8fd164041 --- /dev/null +++ b/Distribution/Data/packets/outgoing/targeting.json @@ -0,0 +1,90 @@ +{ + "category": "Targeting", + "packets": [ + { + "id": "0x6C", + "name": "Target Request", + "description": "Requests the client to select a target.", + "direction": "outgoing", + "isDynamic": false, + "size": 19, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x6C", "description": "Packet identifier" }, + { "name": "allowGround", "type": "bool", "size": 1, "description": "True = allow ground targeting" }, + { "name": "targetId", "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)" } + ], + "related": [ + { "id": "0x6C", "relationship": "response", "note": "Target Response from client" } + ], + "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": "26 (pre-HS) or 30 (HS+)", + "variants": [ + { + "version": "pre-HighSeas", + "name": "Classic", + "size": 26, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x99", "description": "Packet identifier" }, + { "name": "allowGround", "type": "bool", "size": 1, "description": "Allow ground targeting" }, + { "name": "targetId", "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": "multiId", "type": "short", "size": 2, "description": "Multi graphic ID" }, + { "name": "offsetX", "type": "short", "size": 2, "description": "X offset for placement" }, + { "name": "offsetY", "type": "short", "size": 2, "description": "Y offset for placement" }, + { "name": "offsetZ", "type": "short", "size": 2, "description": "Z offset for placement" } + ] + }, + { + "version": "HighSeas+", + "name": "High Seas Extended", + "condition": "Client version >= 7.0.9.0 (HighSeas)", + "size": 30, + "fields": [ + { "name": "packetId", "type": "byte", "size": 1, "value": "0x99", "description": "Packet identifier" }, + { "name": "allowGround", "type": "bool", "size": 1, "description": "Allow ground targeting" }, + { "name": "targetId", "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": "multiId", "type": "short", "size": 2, "description": "Multi graphic ID" }, + { "name": "offsetX", "type": "short", "size": 2, "description": "X offset for placement" }, + { "name": "offsetY", "type": "short", "size": 2, "description": "Y offset for placement" }, + { "name": "offsetZ", "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 + } + } + ] +} diff --git a/Distribution/Data/web/packets.html b/Distribution/Data/web/packets.html new file mode 100644 index 000000000..a6f077a09 --- /dev/null +++ b/Distribution/Data/web/packets.html @@ -0,0 +1,736 @@ + + + + + + + + + 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/Tools/PacketDocs/build-packets.ps1 b/Tools/PacketDocs/build-packets.ps1 new file mode 100644 index 000000000..527f58c08 --- /dev/null +++ b/Tools/PacketDocs/build-packets.ps1 @@ -0,0 +1,136 @@ +# 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 +$rootDir = (Resolve-Path (Join-Path $scriptDir "..\..")).Path +$dataDir = Join-Path $rootDir "Distribution\Data" +$packetsDir = Join-Path $dataDir "packets" +$templateFile = Join-Path $dataDir "packets.html" + +if (-not $OutputPath) { + $OutputPath = Join-Path $dataDir "web\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 to each packet if not present + foreach ($packet in $data.packets) { + if (-not $packet.category -and $data.category) { + $packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -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 to each packet if not present + foreach ($packet in $data.packets) { + if (-not $packet.category -and $data.category) { + $packet | Add-Member -NotePropertyName "category" -NotePropertyValue $data.category -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