132 lines
2.7 KiB
Markdown
132 lines
2.7 KiB
Markdown
# Packet Definition Parser
|
|
|
|
Fast XML-like parser for binary packet structures with versioning and conditional fields.
|
|
|
|
## Basic Syntax
|
|
|
|
```xml
|
|
<packet name="PacketName">
|
|
<version number="1">
|
|
<i32 name="player_id">
|
|
<str16 name="player_name">
|
|
<color name="skin_color">
|
|
</version>
|
|
</packet>
|
|
```
|
|
|
|
## Field Types
|
|
|
|
| Type | Size | Description |
|
|
|------|------|-------------|
|
|
| `i8`, `i16`, `i32`, `i64` | 1-8 bytes | Unsigned integers |
|
|
| `si8`, `si16`, `si32`, `si64` | 1-8 bytes | Signed integers |
|
|
| `f32`, `f64` | 4-8 bytes | Floating point |
|
|
| `str8`, `str16`, `str32` | Variable | Length-prefixed strings |
|
|
| `char` | Fixed | Fixed-size byte array |
|
|
| `color` | 3 bytes | RGB color (r,g,b) |
|
|
| `equip` | 8 bytes | Equipment item |
|
|
| `array` | Variable | Array of substructures |
|
|
|
|
## Multiple Field Names
|
|
|
|
```xml
|
|
<i32 name="player_id,account_id">
|
|
<f32 name="pos_x,pos_y,pos_z">
|
|
```
|
|
|
|
## Conditional Fields
|
|
|
|
```xml
|
|
<str16 name="guild_name" if="flag:has_guild">
|
|
<i8 name="enhancement" if="item_type!=0">
|
|
<color name="aura" if="special_flags&0x01">
|
|
```
|
|
|
|
### Condition Types
|
|
- `flag:name` - Flag is set
|
|
- `!flag:name` - Flag not set
|
|
- `var:name` - Variable exists
|
|
- `!var:name` - Variable doesn't exist
|
|
- `field>=value` - Comparison operators: `>=`, `<=`, `>`, `<`, `==`, `!=`
|
|
- `field&0x01` - Bitwise AND
|
|
|
|
## Arrays
|
|
|
|
```xml
|
|
<i8 name="item_count">
|
|
<array name="items" count="var:item_count">
|
|
<substruct>
|
|
<i32 name="item_id">
|
|
<str16 name="item_name">
|
|
</substruct>
|
|
</array>
|
|
```
|
|
|
|
## Reusable Substructs
|
|
|
|
```xml
|
|
<substruct name="ItemInfo">
|
|
<i32 name="item_id">
|
|
<str16 name="item_name">
|
|
</substruct>
|
|
|
|
<packet name="Inventory">
|
|
<version number="1">
|
|
<i8 name="count">
|
|
<array name="items" count="var:count" substruct="ItemInfo">
|
|
</version>
|
|
</packet>
|
|
```
|
|
|
|
## Field Attributes
|
|
|
|
- `name="field1,field2"` - Field name(s)
|
|
- `if="condition"` - Conditional parsing
|
|
- `size="10"` - Fixed array size for `char` type
|
|
- `count="var:name"` - Array size variable
|
|
- `substruct="Name"` - Reference to substruct
|
|
|
|
## Multiple Versions
|
|
|
|
```xml
|
|
<packet name="PlayerInfo">
|
|
<version number="1">
|
|
<i32 name="id">
|
|
<str16 name="name">
|
|
</version>
|
|
<version number="562">
|
|
<i32 name="id">
|
|
<str16 name="name">
|
|
<color name="skin_color">
|
|
</version>
|
|
</packet>
|
|
```
|
|
|
|
## Comments
|
|
|
|
```xml
|
|
<!-- This is a comment -->
|
|
<packet name="Test"> <!-- Inline comment -->
|
|
<version number="1">
|
|
<i32 name="id"> <!-- Field comment -->
|
|
</version>
|
|
</packet>
|
|
```
|
|
|
|
## Usage
|
|
|
|
```go
|
|
import "eq2emu/internal/parser"
|
|
|
|
// Parse PML content
|
|
packets, err := parser.Parse(pmlContent)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
|
|
// Get packet definition
|
|
packet := packets["PacketName"]
|
|
|
|
// Parse binary data
|
|
result, err := packet.Parse(data, version, flags)
|
|
``` |