eq2go/internal/packets/PARSER.md

6.6 KiB

Packet Definition Parser

Fast XML-like parser for binary packet structures with versioning and conditional fields.

Basic Syntax

<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, double 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

<i32 name="player_id,account_id">
<f32 name="pos_x,pos_y,pos_z">

Conditional Fields

<str16 name="guild_name" if="flag:has_guild">
<i8 name="enhancement" if="item_type!=0">
<color name="aura" if="special_flags&0x01">
<str16 name="description" if="description!>0">

Condition Types

Flag Conditions:

  • flag:name - Flag is set
  • !flag:name - Flag not set

Variable Conditions:

  • var:name - Variable exists and is non-zero
  • !var:name - Variable doesn't exist or is zero

Version Conditions:

  • version>=562 - Version comparisons
  • version<1200 - Supports >=, <=, >, <

Value Comparisons:

  • field>=value - Numeric comparisons
  • field!=0 - Supports >=, <=, >, <, ==, !=

String Length:

  • name!>5 - String longer than 5 chars
  • name!<=100 - String 100 chars or less
  • Supports !>, !<, !>=, !<=, !=

Bitwise Operations:

  • field&0x01 - Bitwise AND with hex value

Complex Logic:

  • cond1,cond2 - OR logic (comma-separated)
  • cond1&cond2 - AND logic (ampersand)
  • version>=562&level>10 - Multiple conditions

Array Context:

  • item_type_%i!=0 - %i substitutes current array index

Groups

Organize related fields with automatic prefixing:

<group name="appearance">
	<color name="skin_color,hair_color,eye_color">
	<str16 name="face_file,hair_file">
</group>
<!-- Creates: appearance_skin_color, appearance_hair_color, etc. -->

Templates

Define reusable field groups that can be injected into packets:

<!-- Define template -->
<template name="position">
	<f32 name="x,y,z">
	<f32 name="heading">
</template>

<template name="appearance">
	<color name="skin_color,hair_color,eye_color">
	<str16 name="face_file,hair_file">
</template>

<!-- Use templates in packets -->
<packet name="PlayerUpdate">
	<version number="1">
		<i32 name="player_id">
		<template use="position">
		<i8 name="level">
		<template use="appearance">
	</version>
</packet>

Templates work with groups for prefixing:

<group name="current">
	<template use="position">
</group>
<!-- Creates: current_x, current_y, current_z, current_heading -->

Arrays

<i8 name="item_count">
<array name="items" count="var:item_count" max_size="100">
	<i32 name="item_id">
	<str16 name="item_name">
</array>

Advanced Field Attributes

Type Switching

<i32 name="stat_value" type2="f32" type2_if="stat_type==6">

Oversized Fields

<i16 name="large_count" oversized="255">
<i32 name="huge_value" oversized="65535">

Field Modifiers

<i8 name="data_array" size="10" default="5">
<str16 name="optional_text" optional="true">
<i32 name="hidden_field" add_to_struct="false" add_type="i16">

Complete Attribute Reference

Attribute Description Example
name Field name(s), comma-separated "id,account_id"
use Template name to inject "position"
if Conditional parsing expression "flag:has_guild"
size Fixed array size for char type "10"
count Array size variable "var:item_count"
substruct Reference to substruct "ItemInfo"
oversized Threshold for oversized handling "255"
type2 Alternative field type "f32"
type2_if Condition for using type2 "stat_type!=6"
default Default value for initialization "0"
max_size Maximum array size limit "100"
optional Field is optional "true"
add_to_struct Include in packet structure "false"
add_type Type when adding to packet "i16"

Reusable Substructs

<substruct name="ItemInfo">
	<i32 name="item_id">
	<str16 name="item_name">
	<i8 name="rarity">
</substruct>

<packet name="Inventory">
	<version number="1">
		<i8 name="count">
		<array name="items" count="var:count" substruct="ItemInfo">
	</version>
</packet>

Multiple Versions

<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

<!-- This is a comment -->
<packet name="Test"> <!-- Inline comment -->
	<version number="1">
		<i32 name="id"> <!-- Field comment -->
	</version>
</packet>

Usage

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 with version and flags
result, err := packet.Parse(data, version, flags)
if err != nil {
	log.Fatal(err)
}

// Access parsed fields
playerID := result["player_id"].(uint32)
playerName := result["player_name"].(common.EQ2String16).Data

Complete Example

<!-- Define reusable templates -->
<template name="position">
	<f32 name="x,y,z">
	<f32 name="heading">
</template>

<template name="appearance">
	<color name="skin_color,hair_color,eye_color">
	<str16 name="face_file,hair_file">
</template>

<substruct name="StatBonus">
	<i8 name="stat_type">
	<i32 name="base_value" type2="f32" type2_if="stat_type==6">
	<i16 name="bonus_value" if="stat_type!=6">
</substruct>

<packet name="PlayerStats">
	<version number="562">
		<i32 name="player_id,account_id">
		<str16 name="player_name">
		<i8 name="level,race,class">
		<template use="position">
		<template use="appearance" if="version>=562">
		<str16 name="guild_name" if="flag:has_guild">
		<i32 name="guild_id" if="flag:has_guild&level>=10">
		<i8 name="stat_count">
		<array name="stats" count="var:stat_count" max_size="50" substruct="StatBonus">
		<i32 name="special_flags">
		<str16 name="special_ability" if="special_flags&0x01">
		<color name="aura_color" if="special_flags&0x02">
		<str16 name="description" if="description!>0">
	</version>
</packet>