Compare commits
10 Commits
35fc2b667b
...
44949f9529
Author | SHA1 | Date | |
---|---|---|---|
44949f9529 | |||
19bc67233b | |||
b2a2e9366b | |||
3f9aae51cb | |||
69f2250ac0 | |||
4b7acea5b9 | |||
c42485f874 | |||
e310437c1b | |||
ca46c5617d | |||
c5a5786400 |
284
internal/packets/PARSER.md
Normal file
284
internal/packets/PARSER.md
Normal file
@ -0,0 +1,284 @@
|
||||
# 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`, `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
|
||||
|
||||
```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">
|
||||
<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:
|
||||
|
||||
```xml
|
||||
<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:
|
||||
|
||||
```xml
|
||||
<!-- 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:
|
||||
|
||||
```xml
|
||||
<group name="current">
|
||||
<template use="position">
|
||||
</group>
|
||||
<!-- Creates: current_x, current_y, current_z, current_heading -->
|
||||
```
|
||||
|
||||
## Arrays
|
||||
|
||||
```xml
|
||||
<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
|
||||
```xml
|
||||
<i32 name="stat_value" type2="f32" type2_if="stat_type==6">
|
||||
```
|
||||
|
||||
### Oversized Fields
|
||||
```xml
|
||||
<i16 name="large_count" oversized="255">
|
||||
<i32 name="huge_value" oversized="65535">
|
||||
```
|
||||
|
||||
### Field Modifiers
|
||||
```xml
|
||||
<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
|
||||
|
||||
```xml
|
||||
<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
|
||||
|
||||
```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 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
|
||||
|
||||
```xml
|
||||
<!-- 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>
|
||||
```
|
8
internal/packets/login/BadLanguageFilter.xml
Normal file
8
internal/packets/login/BadLanguageFilter.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<packet name="BadLanguageFilter">
|
||||
<version number="1">
|
||||
<i16 name="num_words" oversized="255">
|
||||
<array name="words_array" count="var:num_words">
|
||||
<str16 name="word">
|
||||
</array>
|
||||
</version>
|
||||
</packet>
|
276
internal/packets/login/CharSelectProfile.xml
Normal file
276
internal/packets/login/CharSelectProfile.xml
Normal file
@ -0,0 +1,276 @@
|
||||
<packet name="CharSelectProfile">
|
||||
<version number="1">
|
||||
<i32 name="charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,class">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i8 name="version">
|
||||
<i16 name="race_type">
|
||||
<si8 name="skin_color,eye_color" size="3">
|
||||
<equip name="equip" size="21">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<si8 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<si8 name="color,highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<si8 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<si8 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<si8 name="unknown9,eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size,bump_scale">
|
||||
<i16 name="mount">
|
||||
<si8 name="mount_color1,mount_color2,hair_color1,hair_color2,hair_color3" size="3">
|
||||
<i8 name="flags">
|
||||
</version>
|
||||
<version number="373">
|
||||
<i32 name="charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,class">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i8 name="version">
|
||||
<i16 name="race_type">
|
||||
<si8 name="skin_color,eye_color" size="3">
|
||||
<equip name="equip" size="21">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<si8 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<si8 name="color,highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<si8 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<si8 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<si8 name="unknown9,eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size,bump_scale">
|
||||
<i16 name="mount">
|
||||
<si8 name="mount_color1,mount_color2,hair_color1,hair_color2,hair_color3" size="3">
|
||||
<i8 name="flags">
|
||||
</version>
|
||||
<version number="546">
|
||||
<i32 name="charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,class,gender">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i32 name="unknown5">
|
||||
<i8 name="version">
|
||||
<i16 name="race_type">
|
||||
<si8 name="skin_color,eye_color" size="3">
|
||||
<equip name="equip" size="23">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<si8 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<si8 name="color,highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<si8 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<si8 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<si8 name="unknown9,eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size,bump_scale">
|
||||
<i16 name="mount">
|
||||
<si8 name="mount_color1,mount_color2,hair_color1,hair_color2,hair_color3" size="3">
|
||||
<i8 name="unknown11" size="10">
|
||||
<group name="soga">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_colorx,eye_color">
|
||||
<i8 name="Unknown12" size="3">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<color name="hair_color1">
|
||||
<i16 name="chest_type">
|
||||
<color name="hair_color2,hair_color3">
|
||||
<i16 name="hair_type">
|
||||
<color name="hair_type_color,hair_type_highlight_color">
|
||||
<i16 name="hair_face_type">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
</version>
|
||||
<version number="562">
|
||||
<i32 name="version,charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="unknown,race,class,gender">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i32 name="unknown5">
|
||||
<str16 name="server_name">
|
||||
<i32 name="account_id">
|
||||
<i8 name="unknown6" size="2">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="unknown8">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_color,eye_color">
|
||||
<equip name="equip" size="25">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<color name="color,highlight_color">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size">
|
||||
<i8 name="unknown10" size="9">
|
||||
<color name="hair_color1,hair_color2">
|
||||
<i8 name="unknown11,unknown15" size="13,7">
|
||||
</version>
|
||||
<version number="887">
|
||||
<i32 name="version,charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="unknown,race,class,gender">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i32 name="unknown5">
|
||||
<str16 name="server_name">
|
||||
<i32 name="account_id">
|
||||
<i8 name="unknown6" size="2">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="tradeskill_class">
|
||||
<i32 name="tradeskill_level">
|
||||
<i8 name="unknown8">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_color,eye_color">
|
||||
<equip name="equip" size="25">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<color name="color,highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<i16 name="type">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size">
|
||||
<i8 name="unknown10" size="9">
|
||||
<color name="hair_color1,hair_color2">
|
||||
<i8 name="unknown11" size="13">
|
||||
<group name="soga">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_color,eye_color">
|
||||
<i8 name="Unknown12" size="3">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<i16 name="unknown13">
|
||||
<color name="hair_color1,hair_color2,unknown14">
|
||||
<i16 name="hair_type">
|
||||
<color name="hair_type_color,hair_type_highlight_color">
|
||||
<i16 name="hair_face_type">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<i8 name="unknown15" size="7">
|
||||
</version>
|
||||
<version number="60085">
|
||||
<i32 name="version,charid,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="unknown,race,class,gender">
|
||||
<i32 name="level">
|
||||
<str16 name="zone">
|
||||
<i32 name="unknown1,unknown2,created_date,last_played,unknown3,unknown4">
|
||||
<str16 name="zonename2,zonedesc">
|
||||
<i32 name="unknown5">
|
||||
<str16 name="server_name">
|
||||
<i32 name="account_id">
|
||||
<i8 name="unknown6" size="2">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="tradeskill_class">
|
||||
<i32 name="tradeskill_level">
|
||||
<i8 name="unknown8">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_color,eye_color">
|
||||
<equip name="equip" size="25">
|
||||
<group name="hair">
|
||||
<i16 name="type">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="hair_face">
|
||||
<i16 name="type">
|
||||
<color name="color,highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<i16 name="type">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<i16 name="type">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<i16 name="type">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<si8 name="body_size">
|
||||
<i8 name="unknown10" size="9">
|
||||
<color name="hair_color1,hair_color2">
|
||||
<i8 name="unknown11" size="13">
|
||||
<group name="soga">
|
||||
<i16 name="race_type">
|
||||
<color name="skin_color,eye_color">
|
||||
<i8 name="Unknown12" size="3">
|
||||
<si8 name="eye_type,ear_type,eye_brow_type,cheek_type,lip_type,chin_type,nose_type" size="3">
|
||||
<i16 name="unknown13">
|
||||
<color name="hair_color1,hair_color2,unknown14">
|
||||
<i16 name="hair_type">
|
||||
<color name="hair_type_color,hair_type_highlight_color">
|
||||
<i16 name="hair_face_type">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<i8 name="unknown15" size="7">
|
||||
</version>
|
||||
</packet>
|
559
internal/packets/login/CreateCharacter.xml
Normal file
559
internal/packets/login/CreateCharacter.xml
Normal file
@ -0,0 +1,559 @@
|
||||
<packet name="CreateCharacter">
|
||||
<version number="1">
|
||||
<i32 name="account_id,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone">
|
||||
<i8 name="unknown1" size="2">
|
||||
<str16 name="race_file">
|
||||
<f32 name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight" size="3">
|
||||
<i8 name="unknown2" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<f32 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<f32 name="hair_face_color,hair_face_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<f32 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<f32 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<f32 name="unknown9,eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</version>
|
||||
<version number="373">
|
||||
<i32 name="unknown0,account_id,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone">
|
||||
<i8 name="unknown1" size="2">
|
||||
<str16 name="race_file">
|
||||
<f32 name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight" size="3">
|
||||
<i8 name="unknown2" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<f32 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<f32 name="hair_face_color,hair_face_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<f32 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<f32 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<f32 name="unknown9,eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</version>
|
||||
<version number="546">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,cc_unknown_0,version">
|
||||
<str16 name="race_file">
|
||||
<f32 name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight" size="3">
|
||||
<i8 name="unknown2" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<f32 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<f32 name="hair_face_color,hair_face_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<f32 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<f32 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<f32 name="unknown9,eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</version>
|
||||
<version number="561">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id,server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<str16 name="race_file">
|
||||
<f32 name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight" size="3">
|
||||
<i8 name="unknown2" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<f32 name="type_color,type_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<f32 name="hair_face_color,hair_face_highlight_color" size="3">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<f32 name="shirt_color,unknown_chest_color" size="3">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<f32 name="pants_color,unknown_legs_color" size="3">
|
||||
</group>
|
||||
<f32 name="unknown9,eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</version>
|
||||
<version number="562">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,skin_color2,eye_color,hair_color1,hair_color2">
|
||||
<i8 name="unknown8" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown11" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
</version>
|
||||
<version number="869">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,skin_color2,eye_color,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown8" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight,unknown_color1">
|
||||
<i8 name="unknown11" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
</version>
|
||||
<version number="1096">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,skin_color2,eye_color,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown8" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight,unknown_color">
|
||||
<i8 name="unknown11" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
</version>
|
||||
<version number="57080">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<i16 name="unknown10">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,unknown_skin_color2,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown8" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight,unknown_color">
|
||||
<i8 name="unknown11" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
</version>
|
||||
<version number="60085">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level,starting_zone,version">
|
||||
<i16 name="unknown10">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,unknown_skin_color2,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown8" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight,unknown_color">
|
||||
<i8 name="unknown11" size="26">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
</version>
|
||||
<version number="64659">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level">
|
||||
<i32 name="starting_zone">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,skin_color2,eye_color,hair_color1,hair_color2">
|
||||
<i8 name="unknown8" size="38">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown11" size="38">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
<i8 name="unknown13" size="2">
|
||||
</version>
|
||||
<version number="65534">
|
||||
<i8 name="unknown0">
|
||||
<i32 name="unknown1,account_id">
|
||||
<i8 name="unknown3">
|
||||
<i32 name="server_id">
|
||||
<str16 name="name">
|
||||
<i8 name="race,gender,deity,class,level">
|
||||
<i32 name="starting_zone">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,skin_color2,eye_color,hair_color1,hair_color2">
|
||||
<i8 name="unknown8" size="38">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown9">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
<group name="soga">
|
||||
<i8 name="version">
|
||||
<str16 name="race_file">
|
||||
<color name="skin_color,eye_color,hair_color1,hair_color2,hair_highlight">
|
||||
<i8 name="unknown11" size="38">
|
||||
<group name="hair">
|
||||
<str16 name="file">
|
||||
<color name="type_color,type_highlight_color">
|
||||
</group>
|
||||
<group name="face">
|
||||
<str16 name="file">
|
||||
<color name="hair_face_color,hair_face_highlight_color">
|
||||
</group>
|
||||
<group name="wing">
|
||||
<str16 name="file">
|
||||
<color name="color1,color2">
|
||||
</group>
|
||||
<group name="chest">
|
||||
<str16 name="file">
|
||||
<color name="shirt_color,unknown_chest_color">
|
||||
</group>
|
||||
<group name="legs">
|
||||
<str16 name="file">
|
||||
<color name="pants_color,unknown_legs_color">
|
||||
</group>
|
||||
<color name="unknown12">
|
||||
<f32 name="eyes2,ears,eye_brows,cheeks,lips,chin,nose" size="3">
|
||||
<f32 name="body_size,body_age">
|
||||
</group>
|
||||
<i8 name="unknown13" size="2">
|
||||
</version>
|
||||
</packet>
|
17
internal/packets/login/CreateCharacterReply.xml
Normal file
17
internal/packets/login/CreateCharacterReply.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<packet name="CreateCharacterReply">
|
||||
<version number="1">
|
||||
<i32 name="account_id">
|
||||
<i8 name="response">
|
||||
<str16 name="name">
|
||||
</version>
|
||||
<version number="1189">
|
||||
<i32 name="account_id,unknown">
|
||||
<i8 name="response">
|
||||
<str16 name="name">
|
||||
</version>
|
||||
<version number="60085">
|
||||
<i32 name="account_id,unknown">
|
||||
<i8 name="response">
|
||||
<str16 name="name">
|
||||
</version>
|
||||
</packet>
|
6
internal/packets/login/DeleteCharacterRequest.xml
Normal file
6
internal/packets/login/DeleteCharacterRequest.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<packet name="DeleteCharacterRequest">
|
||||
<version number="1">
|
||||
<i32 name="char_id,server_id,unknown">
|
||||
<str16 name="name">
|
||||
</version>
|
||||
</packet>
|
8
internal/packets/login/DeleteCharacterResponse.xml
Normal file
8
internal/packets/login/DeleteCharacterResponse.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<packet name="DeleteCharacterResponse">
|
||||
<version number="1">
|
||||
<i8 name="response">
|
||||
<i32 name="server_id,char_id,account_id">
|
||||
<str16 name="name">
|
||||
<i32 name="max_characters">
|
||||
</version>
|
||||
</packet>
|
360
internal/packets/login/LoginReplyMsg.xml
Normal file
360
internal/packets/login/LoginReplyMsg.xml
Normal file
@ -0,0 +1,360 @@
|
||||
<substruct name="StartingItem">
|
||||
<i32 name="model_id" type2="i16" type2_if="version<57080">
|
||||
<i8 name="slot_id">
|
||||
<i8 name="use_color,use_highlight_color">
|
||||
<color name="model_color,model_highlight_color">
|
||||
</substruct>
|
||||
|
||||
<packet name="LoginReplyMsg">
|
||||
<version number="1">
|
||||
<i8 name="login_response">
|
||||
<str16 name="worldName">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer" size="2">
|
||||
<i32 name="parental_control_next,account_id">
|
||||
</version>
|
||||
|
||||
<version number="284">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="cache_setting_account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="unknown8" size="2">
|
||||
<i8 name="unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
</version>
|
||||
|
||||
<version number="843">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
</version>
|
||||
|
||||
<version number="1096">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6" size="5">
|
||||
<i32 name="unknown7">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username">
|
||||
</version>
|
||||
|
||||
<version number="1142">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6" size="5">
|
||||
<i32 name="unknown7,unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username">
|
||||
</version>
|
||||
|
||||
<version number="1188">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6" size="5">
|
||||
<i32 name="unknown7,unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,unknown12">
|
||||
</version>
|
||||
|
||||
<version number="57080">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6" size="5">
|
||||
<i32 name="unknown7,unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,service">
|
||||
<str16 name="web1,web2,web3,web4,web5,web6,web7,web8,web9">
|
||||
<i8 name="unknown12">
|
||||
<i8 name="lvl90_num_class_items" if="var:unknown10">
|
||||
<array name="lvl90_class_items" count="var:lvl90_num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown13" size="5">
|
||||
</version>
|
||||
|
||||
<version number="60100">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga">
|
||||
<i64 name="unknown5">
|
||||
<i32 name="unknown7">
|
||||
<i16 name="unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9" size="3">
|
||||
<i8 name="unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,service">
|
||||
<i8 name="unknown12">
|
||||
<i8 name="lvl90_num_class_items" if="var:unknown12">
|
||||
<array name="lvl90_class_items" count="var:lvl90_num_class_items" if="var:unknown12">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown13">
|
||||
<i8 name="time_locked_num_class_items" if="var:unknown13">
|
||||
<array name="time_locked_class_items" count="var:time_locked_num_class_items" if="var:unknown13">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown14" size="13">
|
||||
</version>
|
||||
|
||||
<version number="63181">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<i8 name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<i8 name="unknown6" size="5">
|
||||
<i8 name="unknown6a" size="8">
|
||||
<i32 name="unknown7">
|
||||
<i16 name="unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<i8 name="unknown8" size="3">
|
||||
<i8 name="unknown9" size="3">
|
||||
<i8 name="unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,service">
|
||||
<i8 name="unknown12">
|
||||
<i8 name="lvl90_num_class_items" if="var:unknown12">
|
||||
<array name="lvl90_class_items" count="var:lvl90_num_class_items" if="var:unknown12">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown13">
|
||||
<i8 name="time_locked_num_class_items" if="var:unknown13">
|
||||
<array name="time_locked_class_items" count="var:time_locked_num_class_items" if="var:unknown13">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown14" size="9">
|
||||
</version>
|
||||
|
||||
<version number="65534">
|
||||
<i8 name="login_response">
|
||||
<str16 name="world_name">
|
||||
<i8 name="parental_control_flag">
|
||||
<i64 name="parental_control_timer">
|
||||
<i32 name="unknown2,account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga">
|
||||
<str32 name="unknown4,unknown7">
|
||||
<i32 name="race_unknown">
|
||||
<i8 name="unknown8,unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size" if="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,service">
|
||||
<i8 name="unknown12">
|
||||
<i8 name="lvl90_num_class_items" if="var:unknown12">
|
||||
<array name="lvl90_class_items" count="var:lvl90_num_class_items" if="var:unknown12">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown13">
|
||||
<i8 name="time_locked_num_class_items" if="var:unknown13">
|
||||
<array name="time_locked_class_items" count="var:time_locked_num_class_items" if="var:unknown13">
|
||||
<substruct>
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown14" size="13">
|
||||
</version>
|
||||
</packet>
|
25
internal/packets/login/LoginRequest.xml
Normal file
25
internal/packets/login/LoginRequest.xml
Normal file
@ -0,0 +1,25 @@
|
||||
<packet name="LoginRequest">
|
||||
<version number="1">
|
||||
<str16 name="sessionID,sessionRecycleToken,username,password">
|
||||
<i32 name="acctNum,passCode">
|
||||
<i16 name="version">
|
||||
</version>
|
||||
<version number="562">
|
||||
<str16 name="accesscode,unknown1,username,password">
|
||||
<char name="unknown2" size="8">
|
||||
<char name="unknown3" size="2">
|
||||
<i32 name="version">
|
||||
<i16 name="unknown3_dup">
|
||||
<i32 name="unknown4">
|
||||
</version>
|
||||
<version number="1208">
|
||||
<str16 name="accesscode,unknown1,username,password">
|
||||
<char name="unknown2" size="8">
|
||||
<char name="unknown3" size="2">
|
||||
<i16 name="version">
|
||||
<i8 name="unknown4">
|
||||
<i32 name="unknown5a,unknown5b,unknown5c">
|
||||
<i16 name="unknown6">
|
||||
<str16 name="unknown7">
|
||||
</version>
|
||||
</packet>
|
125
internal/packets/login/LoginResponse.xml
Normal file
125
internal/packets/login/LoginResponse.xml
Normal file
@ -0,0 +1,125 @@
|
||||
<substruct name="StartingItem">
|
||||
<i32 name="model_id">
|
||||
<i8 name="slot_id,use_color,use_highlight_color">
|
||||
<color name="model_color,model_highlight_color">
|
||||
</substruct>
|
||||
|
||||
<substruct name="ClassItems">
|
||||
<i8 name="class_id,num_items">
|
||||
<array name="starting_items" count="var:num_items" substruct="StartingItem">
|
||||
</substruct>
|
||||
|
||||
<packet name="LoginResponse">
|
||||
<version number="1">
|
||||
<i8 name="reply_code">
|
||||
<i16 name="unknown01">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<i16 name="unknown06">
|
||||
<i8 name="unknown07,unknown08">
|
||||
<i32 name="unknown09">
|
||||
<i8 name="unknown10">
|
||||
<i32 name="unknown11">
|
||||
<i8 name="unknown12">
|
||||
</version>
|
||||
<version number="546">
|
||||
<i8 name="reply_code">
|
||||
<i16 name="unknown">
|
||||
<i8 name="unknown01">
|
||||
<si32 name="unknown03,unknown04">
|
||||
<char name="unknown15" size="11">
|
||||
<i8 name="unknown02">
|
||||
</version>
|
||||
<version number="561">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="7">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10">
|
||||
</version>
|
||||
<version number="1096">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="7">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10">
|
||||
</version>
|
||||
<version number="1144">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="15">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10">
|
||||
</version>
|
||||
<version number="1153">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="7">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10,unknown11">
|
||||
</version>
|
||||
<version number="1193">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="7">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10,unknown11">
|
||||
<i16 name="unknown12">
|
||||
</version>
|
||||
<version number="57048">
|
||||
<i8 name="reply_code">
|
||||
<char name="unknown01" size="22">
|
||||
<i8 name="unknown02">
|
||||
<si32 name="unknown03,unknown04,unknown05">
|
||||
<i32 name="accountid">
|
||||
<char name="unknown06" size="7">
|
||||
<i32 name="unknown07,unknown08,unknown09,unknown10,unknown11">
|
||||
<char name="unknown12" size="20">
|
||||
</version>
|
||||
<version number="60100">
|
||||
<i8 name="login_response">
|
||||
<str16 name="unknown">
|
||||
<i8 name="parental_control_flag">
|
||||
<i32 name="parental_control_timer">
|
||||
<char name="unknown2" size="8">
|
||||
<i32 name="account_id">
|
||||
<str16 name="unknown3">
|
||||
<i8 name="reset_appearance,do_not_force_soga,unknown4">
|
||||
<i16 name="unknown5">
|
||||
<char name="unknown6" size="5">
|
||||
<i32 name="unknown7">
|
||||
<i16 name="unknown7a">
|
||||
<i8 name="race_unknown">
|
||||
<char name="unknown8" size="3">
|
||||
<char name="unknown9" size="3">
|
||||
<i8 name="unknown10">
|
||||
<i8 name="num_class_items" if="var:unknown10">
|
||||
<array name="class_items" count="var:num_class_items" if="var:unknown10" substruct="ClassItems">
|
||||
<i8 name="unknown_array2_size">
|
||||
<array name="unknown_array2" count="var:unknown_array2_size">
|
||||
<substruct>
|
||||
<i32 name="array2_unknown">
|
||||
</substruct>
|
||||
</array>
|
||||
<i32 name="unknown11,sub_level,race_flag,class_flag">
|
||||
<str16 name="password,username,service">
|
||||
<i8 name="unknown12">
|
||||
<i8 name="lvl90_num_class_items" if="var:unknown12">
|
||||
<array name="lvl90_class_items" count="var:lvl90_num_class_items" if="var:unknown12" substruct="ClassItems">
|
||||
<i8 name="unknown13">
|
||||
<i8 name="time_locked_num_class_items" if="var:unknown13">
|
||||
<array name="time_locked_class_items" count="var:time_locked_num_class_items" if="var:unknown13" substruct="ClassItems">
|
||||
<char name="unknown14" size="13">
|
||||
</version>
|
||||
</packet>
|
10
internal/packets/login/PlayRequest.xml
Normal file
10
internal/packets/login/PlayRequest.xml
Normal file
@ -0,0 +1,10 @@
|
||||
<packet name="PlayRequest">
|
||||
<version number="1">
|
||||
<i32 name="char_id">
|
||||
<str16 name="name">
|
||||
</version>
|
||||
<version number="284">
|
||||
<i32 name="char_id,server_id">
|
||||
<i8 name="unknown" size="3">
|
||||
</version>
|
||||
</packet>
|
29
internal/packets/login/PlayResponse.xml
Normal file
29
internal/packets/login/PlayResponse.xml
Normal file
@ -0,0 +1,29 @@
|
||||
<packet name="PlayResponse">
|
||||
<version number="1">
|
||||
<i8 name="response">
|
||||
<str8 name="server">
|
||||
<i16 name="port">
|
||||
<i32 name="account_id,access_code">
|
||||
</version>
|
||||
<version number="1096">
|
||||
<i8 name="response">
|
||||
<i16 name="unknown1">
|
||||
<str8 name="server">
|
||||
<i16 name="port">
|
||||
<i32 name="account_id,access_code">
|
||||
</version>
|
||||
<version number="60085">
|
||||
<i8 name="response">
|
||||
<i16 name="unknown1" size="3">
|
||||
<str8 name="server">
|
||||
<i16 name="port">
|
||||
<i32 name="account_id,access_code">
|
||||
</version>
|
||||
<version number="60099">
|
||||
<i8 name="response">
|
||||
<i16 name="unknown1" size="3">
|
||||
<str8 name="server">
|
||||
<i16 name="port">
|
||||
<i32 name="account_id,access_code">
|
||||
</version>
|
||||
</packet>
|
83
internal/packets/login/WorldList.xml
Normal file
83
internal/packets/login/WorldList.xml
Normal file
@ -0,0 +1,83 @@
|
||||
<packet name="WorldList">
|
||||
<version number="1">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name">
|
||||
<i8 name="online,locked,unknown2,unknown3,load">
|
||||
</substruct>
|
||||
</array>
|
||||
</version>
|
||||
<version number="373">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name">
|
||||
<i8 name="tag,locked,hidden,unknown">
|
||||
<i16 name="num_players">
|
||||
<i8 name="load,number_online_flag">
|
||||
<i32 name="allowed_races">
|
||||
</substruct>
|
||||
</array>
|
||||
</version>
|
||||
<version number="546">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name,name2">
|
||||
<i8 name="tag,locked,hidden,unknown">
|
||||
<i16 name="num_players">
|
||||
<i8 name="load,number_online_flag,unknown2">
|
||||
<i32 name="allowed_races">
|
||||
</substruct>
|
||||
</array>
|
||||
</version>
|
||||
<version number="562">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name,name2">
|
||||
<i8 name="tag,locked,hidden,unknown">
|
||||
<i16 name="num_players">
|
||||
<i8 name="load,number_online_flag">
|
||||
<i8 name="feature_set" size="2">
|
||||
<i32 name="allowed_races">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown2">
|
||||
</version>
|
||||
<version number="60114">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name,name2">
|
||||
<i8 name="tag,locked,hidden,unknown">
|
||||
<i16 name="num_players">
|
||||
<i8 name="load,number_online_flag">
|
||||
<i8 name="feature_set" size="2">
|
||||
<i32 name="allowed_races">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown2">
|
||||
</version>
|
||||
<version number="65534">
|
||||
<i8 name="num_worlds">
|
||||
<array name="world_list" count="var:num_worlds">
|
||||
<substruct>
|
||||
<i32 name="id">
|
||||
<str16 name="name,name2">
|
||||
<i8 name="tag,locked,hidden,unknown">
|
||||
<i16 name="num_players">
|
||||
<i8 name="load,number_online_flag">
|
||||
<i8 name="feature_set" size="3">
|
||||
<i32 name="allowed_races">
|
||||
</substruct>
|
||||
</array>
|
||||
<i8 name="unknown2">
|
||||
</version>
|
||||
</packet>
|
6
internal/packets/login/WorldUpdate.xml
Normal file
6
internal/packets/login/WorldUpdate.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<packet name="WorldUpdate">
|
||||
<version number="1">
|
||||
<i32 name="server_id">
|
||||
<i8 name="up,locked,unknown1,unknown2">
|
||||
</version>
|
||||
</packet>
|
@ -1,12 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
type BadLanguageFilterWord struct {
|
||||
Word common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type BadLanguageFilter struct {
|
||||
NumWords uint16 `eq2:"int16,oversized=255"`
|
||||
WordsArray []BadLanguageFilterWord `eq2:"array,arraysize=NumWords"`
|
||||
}
|
@ -1,411 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// CharSelectProfile for client version 1
|
||||
type CharSelectProfileV1 struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor []int8 `eq2:"sint8,len=3"`
|
||||
EyeColor []int8 `eq2:"sint8,len=3"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=21"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor []int8 `eq2:"sint8,len=3"`
|
||||
HairTypeHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownChestColor []int8 `eq2:"sint8,len=3"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownLegsColor []int8 `eq2:"sint8,len=3"`
|
||||
Unknown9 []int8 `eq2:"sint8,len=3"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
BumpScale int8 `eq2:"sint8"`
|
||||
Mount uint16 `eq2:"int16"`
|
||||
MountColor1 []int8 `eq2:"sint8,len=3"`
|
||||
MountColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor1 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor3 []int8 `eq2:"sint8,len=3"`
|
||||
Flags uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// CharSelectProfile for client version 373 (same as V1)
|
||||
type CharSelectProfileV373 struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor []int8 `eq2:"sint8,len=3"`
|
||||
EyeColor []int8 `eq2:"sint8,len=3"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=21"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor []int8 `eq2:"sint8,len=3"`
|
||||
HairTypeHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownChestColor []int8 `eq2:"sint8,len=3"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownLegsColor []int8 `eq2:"sint8,len=3"`
|
||||
Unknown9 []int8 `eq2:"sint8,len=3"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
BumpScale int8 `eq2:"sint8"`
|
||||
Mount uint16 `eq2:"int16"`
|
||||
MountColor1 []int8 `eq2:"sint8,len=3"`
|
||||
MountColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor1 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor3 []int8 `eq2:"sint8,len=3"`
|
||||
Flags uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// CharSelectProfile for client version 546
|
||||
type CharSelectProfileV546 struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Unknown5 uint32 `eq2:"int32"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor []int8 `eq2:"sint8,len=3"`
|
||||
EyeColor []int8 `eq2:"sint8,len=3"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=23"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor []int8 `eq2:"sint8,len=3"`
|
||||
HairTypeHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor []int8 `eq2:"sint8,len=3"`
|
||||
HairFaceHighlightColor []int8 `eq2:"sint8,len=3"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownChestColor []int8 `eq2:"sint8,len=3"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor []int8 `eq2:"sint8,len=3"`
|
||||
UnknownLegsColor []int8 `eq2:"sint8,len=3"`
|
||||
Unknown9 []int8 `eq2:"sint8,len=3"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
BumpScale int8 `eq2:"sint8"`
|
||||
Mount uint16 `eq2:"int16"`
|
||||
MountColor1 []int8 `eq2:"sint8,len=3"`
|
||||
MountColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor1 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor2 []int8 `eq2:"sint8,len=3"`
|
||||
HairColor3 []int8 `eq2:"sint8,len=3"`
|
||||
Unknown11 []uint8 `eq2:"int8,len=10"`
|
||||
SogaRaceType uint16 `eq2:"int16"`
|
||||
SogaSkinColorx common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
Unknown12 []uint8 `eq2:"int8,len=3"`
|
||||
SogaEyeType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEarType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
SogaCheekType []int8 `eq2:"sint8,len=3"`
|
||||
SogaLipType []int8 `eq2:"sint8,len=3"`
|
||||
SogaChinType []int8 `eq2:"sint8,len=3"`
|
||||
SogaNoseType []int8 `eq2:"sint8,len=3"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaChestType uint16 `eq2:"int16"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor3 common.EQ2Color `eq2:"color"`
|
||||
SogaHairType uint16 `eq2:"int16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceType uint16 `eq2:"int16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
}
|
||||
|
||||
// CharSelectProfile for client version 562
|
||||
type CharSelectProfileV562 struct {
|
||||
Version uint32 `eq2:"int32"`
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Unknown5 uint32 `eq2:"int32"`
|
||||
ServerName common.EQ2String16 `eq2:"string16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=2"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown8 uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=25"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
Unknown10 []uint8 `eq2:"int8,len=9"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown11 []uint8 `eq2:"int8,len=13"`
|
||||
Unknown15 []uint8 `eq2:"int8,len=7"`
|
||||
}
|
||||
|
||||
// CharSelectProfile for client version 887
|
||||
type CharSelectProfileV887 struct {
|
||||
Version uint32 `eq2:"int32"`
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Unknown5 uint32 `eq2:"int32"`
|
||||
ServerName common.EQ2String16 `eq2:"string16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=2"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
TradeskillClass uint8 `eq2:"int8"`
|
||||
TradeskillLevel uint32 `eq2:"int32"`
|
||||
Unknown8 uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=25"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingType uint16 `eq2:"int16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
Unknown10 []uint8 `eq2:"int8,len=9"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown11 []uint8 `eq2:"int8,len=13"`
|
||||
SogaRaceType uint16 `eq2:"int16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
Unknown12 []uint8 `eq2:"int8,len=3"`
|
||||
SogaEyeType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEarType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
SogaCheekType []int8 `eq2:"sint8,len=3"`
|
||||
SogaLipType []int8 `eq2:"sint8,len=3"`
|
||||
SogaChinType []int8 `eq2:"sint8,len=3"`
|
||||
SogaNoseType []int8 `eq2:"sint8,len=3"`
|
||||
Unknown13 uint16 `eq2:"int16"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown14 common.EQ2Color `eq2:"color"`
|
||||
SogaHairType uint16 `eq2:"int16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceType uint16 `eq2:"int16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
Unknown15 []uint8 `eq2:"int8,len=7"`
|
||||
}
|
||||
|
||||
// CharSelectProfile for client version 60085 (same as 887)
|
||||
type CharSelectProfileV60085 struct {
|
||||
Version uint32 `eq2:"int32"`
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Level uint32 `eq2:"int32"`
|
||||
Zone common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
CreatedDate uint32 `eq2:"int32"`
|
||||
LastPlayed uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
Zonename2 common.EQ2String16 `eq2:"string16"`
|
||||
Zonedesc common.EQ2String16 `eq2:"string16"`
|
||||
Unknown5 uint32 `eq2:"int32"`
|
||||
ServerName common.EQ2String16 `eq2:"string16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=2"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
TradeskillClass uint8 `eq2:"int8"`
|
||||
TradeskillLevel uint32 `eq2:"int32"`
|
||||
Unknown8 uint8 `eq2:"int8"`
|
||||
RaceType uint16 `eq2:"int16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
Equip []common.EQ2EquipmentItem `eq2:"equipment,len=25"`
|
||||
HairType uint16 `eq2:"int16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceType uint16 `eq2:"int16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingType uint16 `eq2:"int16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestType uint16 `eq2:"int16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsType uint16 `eq2:"int16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
EyeType []int8 `eq2:"sint8,len=3"`
|
||||
EarType []int8 `eq2:"sint8,len=3"`
|
||||
EyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
CheekType []int8 `eq2:"sint8,len=3"`
|
||||
LipType []int8 `eq2:"sint8,len=3"`
|
||||
ChinType []int8 `eq2:"sint8,len=3"`
|
||||
NoseType []int8 `eq2:"sint8,len=3"`
|
||||
BodySize int8 `eq2:"sint8"`
|
||||
Unknown10 []uint8 `eq2:"int8,len=9"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown11 []uint8 `eq2:"int8,len=13"`
|
||||
SogaRaceType uint16 `eq2:"int16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
Unknown12 []uint8 `eq2:"int8,len=3"`
|
||||
SogaEyeType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEarType []int8 `eq2:"sint8,len=3"`
|
||||
SogaEyeBrowType []int8 `eq2:"sint8,len=3"`
|
||||
SogaCheekType []int8 `eq2:"sint8,len=3"`
|
||||
SogaLipType []int8 `eq2:"sint8,len=3"`
|
||||
SogaChinType []int8 `eq2:"sint8,len=3"`
|
||||
SogaNoseType []int8 `eq2:"sint8,len=3"`
|
||||
Unknown13 uint16 `eq2:"int16"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown14 common.EQ2Color `eq2:"color"`
|
||||
SogaHairType uint16 `eq2:"int16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceType uint16 `eq2:"int16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
Unknown15 []uint8 `eq2:"int8,len=7"`
|
||||
}
|
@ -1,767 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// CreateCharacter for client version 1
|
||||
type CreateCharacterV1 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Unknown1 []uint8 `eq2:"int8,len=2"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor []float32 `eq2:"float,len=3"`
|
||||
EyeColor []float32 `eq2:"float,len=3"`
|
||||
HairColor1 []float32 `eq2:"float,len=3"`
|
||||
HairColor2 []float32 `eq2:"float,len=3"`
|
||||
HairHighlight []float32 `eq2:"float,len=3"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor []float32 `eq2:"float,len=3"`
|
||||
HairTypeHighlightColor []float32 `eq2:"float,len=3"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor []float32 `eq2:"float,len=3"`
|
||||
HairFaceHighlightColor []float32 `eq2:"float,len=3"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor []float32 `eq2:"float,len=3"`
|
||||
UnknownChestColor []float32 `eq2:"float,len=3"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor []float32 `eq2:"float,len=3"`
|
||||
UnknownLegsColor []float32 `eq2:"float,len=3"`
|
||||
Unknown9 []float32 `eq2:"float,len=3"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 373
|
||||
type CreateCharacterV373 struct {
|
||||
Unknown0 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Unknown1 []uint8 `eq2:"int8,len=2"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor []float32 `eq2:"float,len=3"`
|
||||
EyeColor []float32 `eq2:"float,len=3"`
|
||||
HairColor1 []float32 `eq2:"float,len=3"`
|
||||
HairColor2 []float32 `eq2:"float,len=3"`
|
||||
HairHighlight []float32 `eq2:"float,len=3"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor []float32 `eq2:"float,len=3"`
|
||||
HairTypeHighlightColor []float32 `eq2:"float,len=3"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor []float32 `eq2:"float,len=3"`
|
||||
HairFaceHighlightColor []float32 `eq2:"float,len=3"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor []float32 `eq2:"float,len=3"`
|
||||
UnknownChestColor []float32 `eq2:"float,len=3"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor []float32 `eq2:"float,len=3"`
|
||||
UnknownLegsColor []float32 `eq2:"float,len=3"`
|
||||
Unknown9 []float32 `eq2:"float,len=3"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 546
|
||||
type CreateCharacterV546 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
CcUnknown0 uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor []float32 `eq2:"float,len=3"`
|
||||
EyeColor []float32 `eq2:"float,len=3"`
|
||||
HairColor1 []float32 `eq2:"float,len=3"`
|
||||
HairColor2 []float32 `eq2:"float,len=3"`
|
||||
HairHighlight []float32 `eq2:"float,len=3"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor []float32 `eq2:"float,len=3"`
|
||||
HairTypeHighlightColor []float32 `eq2:"float,len=3"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor []float32 `eq2:"float,len=3"`
|
||||
HairFaceHighlightColor []float32 `eq2:"float,len=3"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor []float32 `eq2:"float,len=3"`
|
||||
UnknownChestColor []float32 `eq2:"float,len=3"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor []float32 `eq2:"float,len=3"`
|
||||
UnknownLegsColor []float32 `eq2:"float,len=3"`
|
||||
Unknown9 []float32 `eq2:"float,len=3"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 561
|
||||
type CreateCharacterV561 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor []float32 `eq2:"float,len=3"`
|
||||
EyeColor []float32 `eq2:"float,len=3"`
|
||||
HairColor1 []float32 `eq2:"float,len=3"`
|
||||
HairColor2 []float32 `eq2:"float,len=3"`
|
||||
HairHighlight []float32 `eq2:"float,len=3"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor []float32 `eq2:"float,len=3"`
|
||||
HairTypeHighlightColor []float32 `eq2:"float,len=3"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor []float32 `eq2:"float,len=3"`
|
||||
HairFaceHighlightColor []float32 `eq2:"float,len=3"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor []float32 `eq2:"float,len=3"`
|
||||
UnknownChestColor []float32 `eq2:"float,len=3"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor []float32 `eq2:"float,len=3"`
|
||||
UnknownLegsColor []float32 `eq2:"float,len=3"`
|
||||
Unknown9 []float32 `eq2:"float,len=3"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 562
|
||||
type CreateCharacterV562 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
SkinColor2 common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=26"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 869
|
||||
type CreateCharacterV869 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
SkinColor2 common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
HairHighlight common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=26"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 1096 (same as 869 but without SogaUnknownColor1)
|
||||
type CreateCharacterV1096 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
SkinColor2 common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
HairHighlight common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=26"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 57080
|
||||
type CreateCharacterV57080 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
Unknown10 uint16 `eq2:"int16"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
UnknownSkinColor2 common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
HairHighlight common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=26"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 60085 (same as 57080)
|
||||
type CreateCharacterV60085 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint8 `eq2:"int8"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
Unknown10 uint16 `eq2:"int16"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
UnknownSkinColor2 common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
HairHighlight common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=26"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=26"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 64659
|
||||
type CreateCharacterV64659 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint32 `eq2:"int32"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
SkinColor2 common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=38"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=38"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
Unknown13 []uint8 `eq2:"int8,len=2"`
|
||||
}
|
||||
|
||||
// CreateCharacter for client version 65534 (same as 64659)
|
||||
type CreateCharacterV65534 struct {
|
||||
Unknown0 uint8 `eq2:"int8"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Race uint8 `eq2:"int8"`
|
||||
Gender uint8 `eq2:"int8"`
|
||||
Deity uint8 `eq2:"int8"`
|
||||
Class uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
StartingZone uint32 `eq2:"int32"`
|
||||
Version uint8 `eq2:"int8"`
|
||||
RaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SkinColor common.EQ2Color `eq2:"color"`
|
||||
SkinColor2 common.EQ2Color `eq2:"color"`
|
||||
EyeColor common.EQ2Color `eq2:"color"`
|
||||
HairColor1 common.EQ2Color `eq2:"color"`
|
||||
HairColor2 common.EQ2Color `eq2:"color"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=38"`
|
||||
HairFile common.EQ2String16 `eq2:"string16"`
|
||||
HairTypeColor common.EQ2Color `eq2:"color"`
|
||||
HairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
FaceFile common.EQ2String16 `eq2:"string16"`
|
||||
HairFaceColor common.EQ2Color `eq2:"color"`
|
||||
HairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
WingFile common.EQ2String16 `eq2:"string16"`
|
||||
WingColor1 common.EQ2Color `eq2:"color"`
|
||||
WingColor2 common.EQ2Color `eq2:"color"`
|
||||
ChestFile common.EQ2String16 `eq2:"string16"`
|
||||
ShirtColor common.EQ2Color `eq2:"color"`
|
||||
UnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
LegsFile common.EQ2String16 `eq2:"string16"`
|
||||
PantsColor common.EQ2Color `eq2:"color"`
|
||||
UnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
Unknown9 common.EQ2Color `eq2:"color"`
|
||||
Eyes2 []float32 `eq2:"float,len=3"`
|
||||
Ears []float32 `eq2:"float,len=3"`
|
||||
EyeBrows []float32 `eq2:"float,len=3"`
|
||||
Cheeks []float32 `eq2:"float,len=3"`
|
||||
Lips []float32 `eq2:"float,len=3"`
|
||||
Chin []float32 `eq2:"float,len=3"`
|
||||
Nose []float32 `eq2:"float,len=3"`
|
||||
BodySize float32 `eq2:"float"`
|
||||
BodyAge float32 `eq2:"float"`
|
||||
SogaVersion uint8 `eq2:"int8"`
|
||||
SogaRaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaSkinColor common.EQ2Color `eq2:"color"`
|
||||
SogaEyeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaHairColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaHairHighlight common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown11 []uint8 `eq2:"int8,len=38"`
|
||||
SogaHairFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairTypeColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairTypeHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaFaceFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaHairFaceColor common.EQ2Color `eq2:"color"`
|
||||
SogaHairFaceHighlightColor common.EQ2Color `eq2:"color"`
|
||||
SogaWingFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaWingColor1 common.EQ2Color `eq2:"color"`
|
||||
SogaWingColor2 common.EQ2Color `eq2:"color"`
|
||||
SogaChestFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaShirtColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownChestColor common.EQ2Color `eq2:"color"`
|
||||
SogaLegsFile common.EQ2String16 `eq2:"string16"`
|
||||
SogaPantsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknownLegsColor common.EQ2Color `eq2:"color"`
|
||||
SogaUnknown12 common.EQ2Color `eq2:"color"`
|
||||
SogaEyes2 []float32 `eq2:"float,len=3"`
|
||||
SogaEars []float32 `eq2:"float,len=3"`
|
||||
SogaEyeBrows []float32 `eq2:"float,len=3"`
|
||||
SogaCheeks []float32 `eq2:"float,len=3"`
|
||||
SogaLips []float32 `eq2:"float,len=3"`
|
||||
SogaChin []float32 `eq2:"float,len=3"`
|
||||
SogaNose []float32 `eq2:"float,len=3"`
|
||||
SogaBodySize float32 `eq2:"float"`
|
||||
SogaBodyAge float32 `eq2:"float"`
|
||||
Unknown13 []uint8 `eq2:"int8,len=2"`
|
||||
}
|
@ -1,26 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// CreateCharacterReply for client version 1
|
||||
type CreateCharacterReplyV1 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Response uint8 `eq2:"int8"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// CreateCharacterReply for client version 1189
|
||||
type CreateCharacterReplyV1189 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown uint32 `eq2:"int32"`
|
||||
Response uint8 `eq2:"int8"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// CreateCharacterReply for client version 60085
|
||||
type CreateCharacterReplyV60085 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown uint32 `eq2:"int32"`
|
||||
Response uint8 `eq2:"int8"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
type DeleteCharacterRequest struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Unknown uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
type DeleteCharacterResponse struct {
|
||||
Response uint8 `eq2:"int8"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
CharID uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
MaxCharacters uint32 `eq2:"int32"`
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
// LoginByNumRequestV1 - Client Version 1
|
||||
type LoginByNumRequestV1 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
Unknown2 []uint32 `eq2:"int32,len=5"`
|
||||
}
|
||||
|
||||
// LoginByNumRequestV562 - Client Version 562
|
||||
type LoginByNumRequestV562 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
Unknown uint32 `eq2:"int32"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
Unknown2 []uint32 `eq2:"int32,len=5"`
|
||||
}
|
||||
|
||||
// LoginByNumRequestV1208 - Client Version 1208
|
||||
type LoginByNumRequestV1208 struct {
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint16 `eq2:"int16"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
Unknown3 []uint32 `eq2:"int32,len=6"`
|
||||
}
|
@ -1,341 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// StartingItemV1 for older client versions (int16 model_id)
|
||||
type StartingItemV1 struct {
|
||||
ModelID uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
UseColor uint8 `eq2:"int8"`
|
||||
UseHighlightColor uint8 `eq2:"int8"`
|
||||
ModelColor common.EQ2Color `eq2:"color"`
|
||||
ModelHighlightColor common.EQ2Color `eq2:"color"`
|
||||
}
|
||||
|
||||
// ClassItem represents class-specific starting equipment
|
||||
type ClassItem struct {
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
NumItems uint8 `eq2:"int8"`
|
||||
StartingItems []StartingItem `eq2:"array,arraysize=NumItems"`
|
||||
}
|
||||
|
||||
// ClassItemV1 for older client versions
|
||||
type ClassItemV1 struct {
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
NumItems uint8 `eq2:"int8"`
|
||||
StartingItems []StartingItemV1 `eq2:"array,arraysize=NumItems"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV1 - Client version 1
|
||||
type LoginReplyMsgV1 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
WorldName common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer []uint32 `eq2:"int32,len=2"`
|
||||
ParentalControlNext uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV284 - Client version 284
|
||||
type LoginReplyMsgV284 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
CacheSettingAccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 uint8 `eq2:"int8"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=2"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItemV1 `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
}
|
||||
|
||||
// LS_LoginReplyMsgV843 - Client version 843
|
||||
type LoginReplyMsgV843 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 uint8 `eq2:"int8"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItemV1 `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
}
|
||||
|
||||
// LS_LoginReplyMsgV1096 - Client version 1096
|
||||
type LoginReplyMsgV1096 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItemV1 `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV1142 - Client version 1142
|
||||
type LoginReplyMsgV1142 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint32 `eq2:"int32"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItemV1 `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV1188 - Client version 1188
|
||||
type LoginReplyMsgV1188 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint32 `eq2:"int32"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItemV1 `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV57080 - Client version 57080
|
||||
type LoginReplyMsgV57080 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint32 `eq2:"int32"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItem `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Service common.EQ2String16 `eq2:"string16"`
|
||||
Web1 common.EQ2String16 `eq2:"string16"`
|
||||
Web2 common.EQ2String16 `eq2:"string16"`
|
||||
Web3 common.EQ2String16 `eq2:"string16"`
|
||||
Web4 common.EQ2String16 `eq2:"string16"`
|
||||
Web5 common.EQ2String16 `eq2:"string16"`
|
||||
Web6 common.EQ2String16 `eq2:"string16"`
|
||||
Web7 common.EQ2String16 `eq2:"string16"`
|
||||
Web8 common.EQ2String16 `eq2:"string16"`
|
||||
Web9 common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Lvl90NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
Lvl90ClassItems []ClassItem `eq2:"array,arraysize=Lvl90NumClassItems,ifvariableset=Unknown10"`
|
||||
Unknown13 []uint8 `eq2:"int8,len=5"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV60100 - Client version 60100
|
||||
type LoginReplyMsgV60100 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown5 uint64 `eq2:"int64"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint16 `eq2:"int16"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItem `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Service common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Lvl90NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown12"`
|
||||
Lvl90ClassItems []ClassItem `eq2:"array,arraysize=Lvl90NumClassItems,ifvariableset=Unknown12"`
|
||||
Unknown13 uint8 `eq2:"int8"`
|
||||
TimeLockedNumClassItems uint8 `eq2:"int8,ifvariableset=Unknown13"`
|
||||
TimeLockedClassItems []ClassItem `eq2:"array,arraysize=TimeLockedNumClassItems,ifvariableset=Unknown13"`
|
||||
Unknown14 []uint8 `eq2:"int8,len=13"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV63181 - Client version 63181
|
||||
type LoginReplyMsgV63181 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown6a []uint8 `eq2:"int8,len=8"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint16 `eq2:"int16"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItem `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Service common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Lvl90NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown12"`
|
||||
Lvl90ClassItems []ClassItem `eq2:"array,arraysize=Lvl90NumClassItems,ifvariableset=Unknown12"`
|
||||
Unknown13 uint8 `eq2:"int8"`
|
||||
TimeLockedNumClassItems uint8 `eq2:"int8,ifvariableset=Unknown13"`
|
||||
TimeLockedClassItems []ClassItem `eq2:"array,arraysize=TimeLockedNumClassItems,ifvariableset=Unknown13"`
|
||||
Unknown14 []uint8 `eq2:"int8,len=9"`
|
||||
}
|
||||
|
||||
// LoginReplyMsgV65534 - Client version 65534 (latest)
|
||||
type LoginReplyMsgV65534 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
WorldName common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint64 `eq2:"int64"`
|
||||
Unknown2 uint32 `eq2:"int32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 common.EQ2String32 `eq2:"string32"`
|
||||
Unknown7 common.EQ2String32 `eq2:"string32"`
|
||||
RaceUnknown uint32 `eq2:"int32"`
|
||||
Unknown8 uint8 `eq2:"int8"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItem `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size,ifvariableset=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Service common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Lvl90NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown12"`
|
||||
Lvl90ClassItems []ClassItem `eq2:"array,arraysize=Lvl90NumClassItems,ifvariableset=Unknown12"`
|
||||
Unknown13 uint8 `eq2:"int8"`
|
||||
TimeLockedNumClassItems uint8 `eq2:"int8,ifvariableset=Unknown13"`
|
||||
TimeLockedClassItems []ClassItem `eq2:"array,arraysize=TimeLockedNumClassItems,ifvariableset=Unknown13"`
|
||||
Unknown14 []uint8 `eq2:"int8,len=13"`
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// LoginRequest for client version 1
|
||||
type LoginRequestV1 struct {
|
||||
SessionID common.EQ2String16 `eq2:"string16"`
|
||||
SessionRecycleToken common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
AcctNum uint32 `eq2:"int32"`
|
||||
PassCode uint32 `eq2:"int32"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
}
|
||||
|
||||
// LoginRequest for client version 562
|
||||
type LoginRequestV562 struct {
|
||||
AccessCode common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
Unknown3 []uint8 `eq2:"int8,len=2"`
|
||||
Version uint32 `eq2:"int32"`
|
||||
Unknown3b uint16 `eq2:"int16"`
|
||||
Unknown4 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginRequest for client version 1208
|
||||
type LoginRequestV1208 struct {
|
||||
AccessCode common.EQ2String16 `eq2:"string16"`
|
||||
Unknown1 common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
Unknown3 []uint8 `eq2:"int8,len=2"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 []uint32 `eq2:"int32,len=3"`
|
||||
Unknown6 uint16 `eq2:"int16"`
|
||||
Unknown7 common.EQ2String16 `eq2:"string16"`
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// LoginResponse for client version 1
|
||||
type LoginResponseV1 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 uint16 `eq2:"int16"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 uint16 `eq2:"int16"`
|
||||
Unknown07 uint8 `eq2:"int8"`
|
||||
Unknown08 uint8 `eq2:"int8"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 546
|
||||
type LoginResponseV546 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown uint16 `eq2:"int16"`
|
||||
Unknown01 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown15 []uint8 `eq2:"int8,len=11"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 561
|
||||
type LoginResponseV561 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=7"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 1096
|
||||
type LoginResponseV1096 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=7"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 1144
|
||||
type LoginResponseV1144 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=15"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 1153
|
||||
type LoginResponseV1153 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=7"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 1193
|
||||
type LoginResponseV1193 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=7"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
Unknown12 uint16 `eq2:"int16"`
|
||||
}
|
||||
|
||||
// ClassItems represents class-specific starting items
|
||||
type ClassItems struct {
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
NumItems uint8 `eq2:"int8"`
|
||||
StartingItems []StartingItem `eq2:"array,arraysize=NumItems"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 60100 - most complex version
|
||||
type LoginResponseV60100 struct {
|
||||
LoginResponse uint8 `eq2:"int8"`
|
||||
Unknown common.EQ2String16 `eq2:"string16"`
|
||||
ParentalControlFlag uint8 `eq2:"int8"`
|
||||
ParentalControlTimer uint32 `eq2:"int32"`
|
||||
Unknown2 []uint8 `eq2:"int8,len=8"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown3 common.EQ2String16 `eq2:"string16"`
|
||||
ResetAppearance uint8 `eq2:"int8"`
|
||||
DoNotForceSoga uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Unknown5 uint16 `eq2:"int16"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=5"`
|
||||
Unknown7 uint32 `eq2:"int32"`
|
||||
Unknown7a uint16 `eq2:"int16"`
|
||||
RaceUnknown uint8 `eq2:"int8"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown9 []uint8 `eq2:"int8,len=3"`
|
||||
Unknown10 uint8 `eq2:"int8"`
|
||||
NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown10"`
|
||||
ClassItems []ClassItems `eq2:"array,arraysize=NumClassItems,ifvariableset=Unknown10"`
|
||||
UnknownArray2Size uint8 `eq2:"int8"`
|
||||
UnknownArray2 []UnknownArray2Item `eq2:"array,arraysize=UnknownArray2Size"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
SubLevel uint32 `eq2:"int32"`
|
||||
RaceFlag uint32 `eq2:"int32"`
|
||||
ClassFlag uint32 `eq2:"int32"`
|
||||
Password common.EQ2String16 `eq2:"string16"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Service common.EQ2String16 `eq2:"string16"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Lvl90NumClassItems uint8 `eq2:"int8,ifvariableset=Unknown12"`
|
||||
Lvl90ClassItems []ClassItems `eq2:"array,arraysize=Lvl90NumClassItems,ifvariableset=Unknown12"`
|
||||
Unknown13 uint8 `eq2:"int8"`
|
||||
TimeLockedNumClassItems uint8 `eq2:"int8,ifvariableset=Unknown13"`
|
||||
TimeLockedClassItems []ClassItems `eq2:"array,arraysize=TimeLockedNumClassItems,ifvariableset=Unknown13"`
|
||||
Unknown14 []uint8 `eq2:"int8,len=13"`
|
||||
}
|
||||
|
||||
// LoginResponse for client version 57048
|
||||
type LoginResponseV57048 struct {
|
||||
ReplyCode uint8 `eq2:"int8"`
|
||||
Unknown01 []uint8 `eq2:"int8,len=22"`
|
||||
Unknown02 uint8 `eq2:"int8"`
|
||||
Unknown03 int32 `eq2:"sint32"`
|
||||
Unknown04 int32 `eq2:"sint32"`
|
||||
Unknown05 int32 `eq2:"sint32"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
Unknown06 []uint8 `eq2:"int8,len=7"`
|
||||
Unknown07 uint32 `eq2:"int32"`
|
||||
Unknown08 uint32 `eq2:"int32"`
|
||||
Unknown09 uint32 `eq2:"int32"`
|
||||
Unknown10 uint32 `eq2:"int32"`
|
||||
Unknown11 uint32 `eq2:"int32"`
|
||||
Unknown12 []uint32 `eq2:"int32,len=5"`
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// PlayRequest for client version 1
|
||||
type PlayRequestV1 struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
// PlayRequest for client version 284
|
||||
type PlayRequestV284 struct {
|
||||
CharID uint32 `eq2:"int32"`
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Unknown []uint8 `eq2:"int8,len=3"`
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// PlayResponse for client version 1
|
||||
type PlayResponseV1 struct {
|
||||
Response uint8 `eq2:"int8"`
|
||||
Server common.EQ2String8 `eq2:"string8"`
|
||||
Port uint16 `eq2:"int16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// PlayResponse for client version 1096
|
||||
type PlayResponseV1096 struct {
|
||||
Response uint8 `eq2:"int8"`
|
||||
Unknown1 uint16 `eq2:"int16"`
|
||||
Server common.EQ2String8 `eq2:"string8"`
|
||||
Port uint16 `eq2:"int16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// PlayResponse for client version 60085
|
||||
type PlayResponseV60085 struct {
|
||||
Response uint8 `eq2:"int8"`
|
||||
Unknown1 []uint16 `eq2:"int16,len=3"`
|
||||
Server common.EQ2String8 `eq2:"string8"`
|
||||
Port uint16 `eq2:"int16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// PlayResponse for client version 60099
|
||||
type PlayResponseV60099 struct {
|
||||
Response uint8 `eq2:"int8"`
|
||||
Unknown1 []uint16 `eq2:"int16,len=3"`
|
||||
Server common.EQ2String8 `eq2:"string8"`
|
||||
Port uint16 `eq2:"int16"`
|
||||
AccountID uint32 `eq2:"int32"`
|
||||
AccessCode uint32 `eq2:"int32"`
|
||||
}
|
@ -1,131 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// World for client version 1
|
||||
type WorldV1 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Online uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
Unknown3 uint8 `eq2:"int8"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// WorldList for client version 1
|
||||
type WorldListV1 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV1 `eq2:"array,arraysize=NumWorlds"`
|
||||
}
|
||||
|
||||
// World for client version 373
|
||||
type WorldV373 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Tag uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Hidden uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
NumPlayers uint16 `eq2:"int16"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
NumberOnlineFlag uint8 `eq2:"int8"`
|
||||
AllowedRaces uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// WorldList for client version 373
|
||||
type WorldListV373 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV373 `eq2:"array,arraysize=NumWorlds"`
|
||||
}
|
||||
|
||||
// World for client version 546
|
||||
type WorldV546 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Name2 common.EQ2String16 `eq2:"string16"`
|
||||
Tag uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Hidden uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
NumPlayers uint16 `eq2:"int16"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
NumberOnlineFlag uint8 `eq2:"int8"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
AllowedRaces uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// WorldList for client version 546
|
||||
type WorldListV546 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV546 `eq2:"array,arraysize=NumWorlds"`
|
||||
}
|
||||
|
||||
// World for client version 562
|
||||
type WorldV562 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Name2 common.EQ2String16 `eq2:"string16"`
|
||||
Tag uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Hidden uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
NumPlayers uint16 `eq2:"int16"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
NumberOnlineFlag uint8 `eq2:"int8"`
|
||||
FeatureSet []uint8 `eq2:"int8,len=2"`
|
||||
AllowedRaces uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// WorldList for client version 562
|
||||
type WorldListV562 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV562 `eq2:"array,arraysize=NumWorlds"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// World for client version 60114
|
||||
type WorldV60114 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Name2 common.EQ2String16 `eq2:"string16"`
|
||||
Tag uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Hidden uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
NumPlayers uint16 `eq2:"int16"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
NumberOnlineFlag uint8 `eq2:"int8"`
|
||||
FeatureSet []uint8 `eq2:"int8,len=2"`
|
||||
AllowedRaces uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// WorldList for client version 60114
|
||||
type WorldListV60114 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV60114 `eq2:"array,arraysize=NumWorlds"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// World for client version 65534
|
||||
type WorldV65534 struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Name2 common.EQ2String16 `eq2:"string16"`
|
||||
Tag uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Hidden uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
NumPlayers uint16 `eq2:"int16"`
|
||||
Load uint8 `eq2:"int8"`
|
||||
NumberOnlineFlag uint8 `eq2:"int8"`
|
||||
FeatureSet []uint8 `eq2:"int8,len=3"`
|
||||
AllowedRaces uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// WorldList for client version 65534
|
||||
type WorldListV65534 struct {
|
||||
NumWorlds uint8 `eq2:"int8"`
|
||||
WorldList []WorldV65534 `eq2:"array,arraysize=NumWorlds"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
type WorldUpdate struct {
|
||||
ServerID uint32 `eq2:"int32"`
|
||||
Up uint8 `eq2:"int8"`
|
||||
Locked uint8 `eq2:"int8"`
|
||||
Unknown1 uint8 `eq2:"int8"`
|
||||
Unknown2 uint8 `eq2:"int8"`
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import (
|
||||
"eq2emu/internal/common"
|
||||
"eq2emu/internal/packets/parser"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type UnknownArray2Item struct {
|
||||
Array2Unknown uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// StartingItem represents equipment items for character creation
|
||||
type StartingItem struct {
|
||||
ModelID uint32 `eq2:"int32"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
UseColor uint8 `eq2:"int8"`
|
||||
UseHighlightColor uint8 `eq2:"int8"`
|
||||
ModelColor common.EQ2Color `eq2:"color"`
|
||||
ModelHighlightColor common.EQ2Color `eq2:"color"`
|
||||
}
|
||||
|
||||
func RegisterLoginServerStructs(registry *parser.VersionRegistry) {
|
||||
// CreateCharacterReply
|
||||
registry.RegisterStruct("CreateCharacterReply", "1", reflect.TypeOf(CreateCharacterReplyV1{}))
|
||||
registry.RegisterStruct("CreateCharacterReply", "1189", reflect.TypeOf(CreateCharacterReplyV1189{}))
|
||||
registry.RegisterStruct("CreateCharacterReply", "60085", reflect.TypeOf(CreateCharacterReplyV60085{}))
|
||||
|
||||
// DeleteCharacterRequest
|
||||
registry.RegisterStruct("DeleteCharacterRequest", "1", reflect.TypeOf(DeleteCharacterRequest{}))
|
||||
|
||||
// DeleteCharacterResponse
|
||||
registry.RegisterStruct("DeleteCharacterResponse", "1", reflect.TypeOf(DeleteCharacterResponse{}))
|
||||
|
||||
// LoginRequest
|
||||
registry.RegisterStruct("LoginRequest", "1", reflect.TypeOf(LoginRequestV1{}))
|
||||
registry.RegisterStruct("LoginRequest", "562", reflect.TypeOf(LoginRequestV562{}))
|
||||
registry.RegisterStruct("LoginRequest", "1208", reflect.TypeOf(LoginRequestV1208{}))
|
||||
|
||||
// LoginResponse
|
||||
registry.RegisterStruct("LoginResponse", "1", reflect.TypeOf(LoginResponseV1{}))
|
||||
registry.RegisterStruct("LoginResponse", "546", reflect.TypeOf(LoginResponseV546{}))
|
||||
registry.RegisterStruct("LoginResponse", "561", reflect.TypeOf(LoginResponseV561{}))
|
||||
registry.RegisterStruct("LoginResponse", "1096", reflect.TypeOf(LoginResponseV1096{}))
|
||||
registry.RegisterStruct("LoginResponse", "1144", reflect.TypeOf(LoginResponseV1144{}))
|
||||
registry.RegisterStruct("LoginResponse", "1153", reflect.TypeOf(LoginResponseV1153{}))
|
||||
registry.RegisterStruct("LoginResponse", "1193", reflect.TypeOf(LoginResponseV1193{}))
|
||||
registry.RegisterStruct("LoginResponse", "57048", reflect.TypeOf(LoginResponseV57048{}))
|
||||
registry.RegisterStruct("LoginResponse", "60100", reflect.TypeOf(LoginResponseV60100{}))
|
||||
|
||||
// PlayRequest
|
||||
registry.RegisterStruct("PlayRequest", "1", reflect.TypeOf(PlayRequestV1{}))
|
||||
registry.RegisterStruct("PlayRequest", "284", reflect.TypeOf(PlayRequestV284{}))
|
||||
|
||||
// PlayResponse
|
||||
registry.RegisterStruct("PlayResponse", "1", reflect.TypeOf(PlayResponseV1{}))
|
||||
registry.RegisterStruct("PlayResponse", "1096", reflect.TypeOf(PlayResponseV1096{}))
|
||||
registry.RegisterStruct("PlayResponse", "60085", reflect.TypeOf(PlayResponseV60085{}))
|
||||
registry.RegisterStruct("PlayResponse", "60099", reflect.TypeOf(PlayResponseV60099{}))
|
||||
|
||||
// WorldList
|
||||
registry.RegisterStruct("WorldList", "1", reflect.TypeOf(WorldListV1{}))
|
||||
registry.RegisterStruct("WorldList", "373", reflect.TypeOf(WorldListV373{}))
|
||||
registry.RegisterStruct("WorldList", "546", reflect.TypeOf(WorldListV546{}))
|
||||
registry.RegisterStruct("WorldList", "562", reflect.TypeOf(WorldListV562{}))
|
||||
registry.RegisterStruct("WorldList", "60114", reflect.TypeOf(WorldListV60114{}))
|
||||
registry.RegisterStruct("WorldList", "65534", reflect.TypeOf(WorldListV65534{}))
|
||||
|
||||
// WorldUpdate
|
||||
registry.RegisterStruct("WorldUpdate", "1", reflect.TypeOf(WorldUpdate{}))
|
||||
|
||||
// LoginReplyMsg
|
||||
registry.RegisterStruct("LoginReplyMsg", "1", reflect.TypeOf(LoginReplyMsgV1{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "284", reflect.TypeOf(LoginReplyMsgV284{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "843", reflect.TypeOf(LoginReplyMsgV843{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "1096", reflect.TypeOf(LoginReplyMsgV1096{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "1142", reflect.TypeOf(LoginReplyMsgV1142{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "1188", reflect.TypeOf(LoginReplyMsgV1188{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "57080", reflect.TypeOf(LoginReplyMsgV57080{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "60100", reflect.TypeOf(LoginReplyMsgV60100{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "63181", reflect.TypeOf(LoginReplyMsgV63181{}))
|
||||
registry.RegisterStruct("LoginReplyMsg", "65534", reflect.TypeOf(LoginReplyMsgV65534{}))
|
||||
|
||||
// LoginByNumRequest
|
||||
registry.RegisterStruct("LoginByNumRequest", "1", reflect.TypeOf(LoginByNumRequestV1{}))
|
||||
registry.RegisterStruct("LoginByNumRequest", "562", reflect.TypeOf(LoginByNumRequestV562{}))
|
||||
registry.RegisterStruct("LoginByNumRequest", "1208", reflect.TypeOf(LoginByNumRequestV1208{}))
|
||||
|
||||
// BadLanguageFilter
|
||||
registry.RegisterStruct("BadLanguageFilter", "1", reflect.TypeOf(BadLanguageFilter{}))
|
||||
|
||||
// CharSelectProfile
|
||||
registry.RegisterStruct("CharSelectProfile", "1", reflect.TypeOf(CharSelectProfileV1{}))
|
||||
registry.RegisterStruct("CharSelectProfile", "373", reflect.TypeOf(CharSelectProfileV373{}))
|
||||
registry.RegisterStruct("CharSelectProfile", "546", reflect.TypeOf(CharSelectProfileV546{}))
|
||||
registry.RegisterStruct("CharSelectProfile", "562", reflect.TypeOf(CharSelectProfileV562{}))
|
||||
registry.RegisterStruct("CharSelectProfile", "887", reflect.TypeOf(CharSelectProfileV887{}))
|
||||
registry.RegisterStruct("CharSelectProfile", "60085", reflect.TypeOf(CharSelectProfileV60085{}))
|
||||
|
||||
// CreateCharacter
|
||||
registry.RegisterStruct("CreateCharacter", "1", reflect.TypeOf(CreateCharacterV1{}))
|
||||
registry.RegisterStruct("CreateCharacter", "373", reflect.TypeOf(CreateCharacterV373{}))
|
||||
registry.RegisterStruct("CreateCharacter", "546", reflect.TypeOf(CreateCharacterV546{}))
|
||||
registry.RegisterStruct("CreateCharacter", "561", reflect.TypeOf(CreateCharacterV561{}))
|
||||
registry.RegisterStruct("CreateCharacter", "562", reflect.TypeOf(CreateCharacterV562{}))
|
||||
registry.RegisterStruct("CreateCharacter", "869", reflect.TypeOf(CreateCharacterV869{}))
|
||||
registry.RegisterStruct("CreateCharacter", "1096", reflect.TypeOf(CreateCharacterV1096{}))
|
||||
registry.RegisterStruct("CreateCharacter", "57080", reflect.TypeOf(CreateCharacterV57080{}))
|
||||
registry.RegisterStruct("CreateCharacter", "60085", reflect.TypeOf(CreateCharacterV60085{}))
|
||||
registry.RegisterStruct("CreateCharacter", "64659", reflect.TypeOf(CreateCharacterV64659{}))
|
||||
registry.RegisterStruct("CreateCharacter", "65534", reflect.TypeOf(CreateCharacterV65534{}))
|
||||
}
|
@ -1,641 +0,0 @@
|
||||
package ls_structs
|
||||
|
||||
import (
|
||||
"eq2emu/internal/packets/parser"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDeleteCharacterRequest(t *testing.T) {
|
||||
// CharID=12345, ServerID=1, Unknown=0, Name="TestChar"
|
||||
data := []byte{
|
||||
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||
0x00, 0x00, 0x00, 0x00, // Unknown = 0
|
||||
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet DeleteCharacterRequest
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.CharID != 12345 {
|
||||
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||
}
|
||||
if packet.ServerID != 1 {
|
||||
t.Errorf("Expected ServerID=1, got %d", packet.ServerID)
|
||||
}
|
||||
if packet.Name.Data != "TestChar" {
|
||||
t.Errorf("Expected Name='TestChar', got '%s'", packet.Name.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteCharacterResponse(t *testing.T) {
|
||||
// Response=1, ServerID=1, CharID=12345, AccountID=54321, Name="TestChar", MaxCharacters=8
|
||||
data := []byte{
|
||||
0x01, // Response = 1
|
||||
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||
0x08, 0x00, 0x00, 0x00, // MaxCharacters = 8
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet DeleteCharacterResponse
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.Response != 1 {
|
||||
t.Errorf("Expected Response=1, got %d", packet.Response)
|
||||
}
|
||||
if packet.CharID != 12345 {
|
||||
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||
}
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
if packet.MaxCharacters != 8 {
|
||||
t.Errorf("Expected MaxCharacters=8, got %d", packet.MaxCharacters)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCharacterReplyV1(t *testing.T) {
|
||||
// AccountID=54321, Response=0, Name="NewChar"
|
||||
data := []byte{
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x00, // Response = 0
|
||||
0x07, 0x00, 'N', 'e', 'w', 'C', 'h', 'a', 'r', // Name = "NewChar"
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet CreateCharacterReplyV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
if packet.Response != 0 {
|
||||
t.Errorf("Expected Response=0, got %d", packet.Response)
|
||||
}
|
||||
if packet.Name.Data != "NewChar" {
|
||||
t.Errorf("Expected Name='NewChar', got '%s'", packet.Name.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateCharacterReplyV1189(t *testing.T) {
|
||||
// AccountID=54321, Unknown=100, Response=0, Name="NewChar"
|
||||
data := []byte{
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x64, 0x00, 0x00, 0x00, // Unknown = 100
|
||||
0x00, // Response = 0
|
||||
0x07, 0x00, 'N', 'e', 'w', 'C', 'h', 'a', 'r', // Name = "NewChar"
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet CreateCharacterReplyV1189
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
if packet.Unknown != 100 {
|
||||
t.Errorf("Expected Unknown=100, got %d", packet.Unknown)
|
||||
}
|
||||
if packet.Response != 0 {
|
||||
t.Errorf("Expected Response=0, got %d", packet.Response)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginRequestV1(t *testing.T) {
|
||||
data := []byte{
|
||||
// SessionID = "session123"
|
||||
0x0A, 0x00, 's', 'e', 's', 's', 'i', 'o', 'n', '1', '2', '3',
|
||||
// SessionRecycleToken = "token456"
|
||||
0x08, 0x00, 't', 'o', 'k', 'e', 'n', '4', '5', '6',
|
||||
// Username = "testuser"
|
||||
0x08, 0x00, 't', 'e', 's', 't', 'u', 's', 'e', 'r',
|
||||
// Password = "testpass"
|
||||
0x08, 0x00, 't', 'e', 's', 't', 'p', 'a', 's', 's',
|
||||
0x31, 0xD4, 0x00, 0x00, // AcctNum = 54321
|
||||
0x39, 0x30, 0x00, 0x00, // PassCode = 12345
|
||||
0xDC, 0x05, // Version = 1500
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginRequestV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.SessionID.Data != "session123" {
|
||||
t.Errorf("Expected SessionID='session123', got '%s'", packet.SessionID.Data)
|
||||
}
|
||||
if packet.Username.Data != "testuser" {
|
||||
t.Errorf("Expected Username='testuser', got '%s'", packet.Username.Data)
|
||||
}
|
||||
if packet.AcctNum != 54321 {
|
||||
t.Errorf("Expected AcctNum=54321, got %d", packet.AcctNum)
|
||||
}
|
||||
if packet.Version != 1500 {
|
||||
t.Errorf("Expected Version=1500, got %d", packet.Version)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginByNumRequestV1(t *testing.T) {
|
||||
data := []byte{
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x39, 0x30, 0x00, 0x00, // AccessCode = 12345
|
||||
0xDC, 0x05, // Version = 1500
|
||||
// Unknown2 = [1, 2, 3, 4, 5]
|
||||
0x01, 0x00, 0x00, 0x00,
|
||||
0x02, 0x00, 0x00, 0x00,
|
||||
0x03, 0x00, 0x00, 0x00,
|
||||
0x04, 0x00, 0x00, 0x00,
|
||||
0x05, 0x00, 0x00, 0x00,
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginByNumRequestV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
if packet.AccessCode != 12345 {
|
||||
t.Errorf("Expected AccessCode=12345, got %d", packet.AccessCode)
|
||||
}
|
||||
if packet.Version != 1500 {
|
||||
t.Errorf("Expected Version=1500, got %d", packet.Version)
|
||||
}
|
||||
if len(packet.Unknown2) != 5 {
|
||||
t.Errorf("Expected Unknown2 length=5, got %d", len(packet.Unknown2))
|
||||
}
|
||||
if packet.Unknown2[0] != 1 || packet.Unknown2[4] != 5 {
|
||||
t.Errorf("Expected Unknown2=[1,2,3,4,5], got %v", packet.Unknown2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlayRequestV1(t *testing.T) {
|
||||
data := []byte{
|
||||
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet PlayRequestV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.CharID != 12345 {
|
||||
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||
}
|
||||
if packet.Name.Data != "TestChar" {
|
||||
t.Errorf("Expected Name='TestChar', got '%s'", packet.Name.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPlayResponseV1(t *testing.T) {
|
||||
data := []byte{
|
||||
0x01, // Response = 1
|
||||
0x09, '1', '2', '7', '.', '0', '.', '0', '.', '1', // Server = "127.0.0.1"
|
||||
0xC4, 0x09, // Port = 2500
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x39, 0x30, 0x00, 0x00, // AccessCode = 12345
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet PlayResponseV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.Response != 1 {
|
||||
t.Errorf("Expected Response=1, got %d", packet.Response)
|
||||
}
|
||||
if packet.Server.Data != "127.0.0.1" {
|
||||
t.Errorf("Expected Server='127.0.0.1', got '%s'", packet.Server.Data)
|
||||
}
|
||||
if packet.Port != 2500 {
|
||||
t.Errorf("Expected Port=2500, got %d", packet.Port)
|
||||
}
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorldListV1(t *testing.T) {
|
||||
data := []byte{
|
||||
0x02, // NumWorlds = 2
|
||||
// World 1
|
||||
0x01, 0x00, 0x00, 0x00, // ID = 1
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Name = "Antonia"
|
||||
0x01, // Online = 1
|
||||
0x00, // Locked = 0
|
||||
0x00, // Unknown2 = 0
|
||||
0x00, // Unknown3 = 0
|
||||
0x32, // Load = 50
|
||||
// World 2
|
||||
0x02, 0x00, 0x00, 0x00, // ID = 2
|
||||
0x08, 0x00, 'N', 'a', 'g', 'a', 'f', 'e', 'n', ' ', // Name = "Nagafen "
|
||||
0x01, // Online = 1
|
||||
0x01, // Locked = 1
|
||||
0x00, // Unknown2 = 0
|
||||
0x00, // Unknown3 = 0
|
||||
0x64, // Load = 100
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet WorldListV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.NumWorlds != 2 {
|
||||
t.Errorf("Expected NumWorlds=2, got %d", packet.NumWorlds)
|
||||
}
|
||||
if len(packet.WorldList) != 2 {
|
||||
t.Errorf("Expected 2 worlds, got %d", len(packet.WorldList))
|
||||
}
|
||||
if packet.WorldList[0].Name.Data != "Antonia" {
|
||||
t.Errorf("Expected first world 'Antonia', got '%s'", packet.WorldList[0].Name.Data)
|
||||
}
|
||||
if packet.WorldList[0].Online != 1 {
|
||||
t.Errorf("Expected first world online=1, got %d", packet.WorldList[0].Online)
|
||||
}
|
||||
if packet.WorldList[1].Locked != 1 {
|
||||
t.Errorf("Expected second world locked=1, got %d", packet.WorldList[1].Locked)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorldListV373(t *testing.T) {
|
||||
data := []byte{
|
||||
0x01, // NumWorlds = 1
|
||||
// World 1
|
||||
0x01, 0x00, 0x00, 0x00, // ID = 1
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Name = "Antonia"
|
||||
0x01, // Tag = 1
|
||||
0x00, // Locked = 0
|
||||
0x00, // Hidden = 0
|
||||
0x00, // Unknown = 0
|
||||
0x64, 0x00, // NumPlayers = 100
|
||||
0x32, // Load = 50
|
||||
0x01, // NumberOnlineFlag = 1
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // AllowedRaces = 0xFFFFFFFF
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet WorldListV373
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.NumWorlds != 1 {
|
||||
t.Errorf("Expected NumWorlds=1, got %d", packet.NumWorlds)
|
||||
}
|
||||
if packet.WorldList[0].NumPlayers != 100 {
|
||||
t.Errorf("Expected NumPlayers=100, got %d", packet.WorldList[0].NumPlayers)
|
||||
}
|
||||
if packet.WorldList[0].AllowedRaces != 0xFFFFFFFF {
|
||||
t.Errorf("Expected AllowedRaces=0xFFFFFFFF, got %d", packet.WorldList[0].AllowedRaces)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginReplyMsgV1(t *testing.T) {
|
||||
data := []byte{
|
||||
0x00, // LoginResponse = 0 (success)
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // WorldName = "Antonia"
|
||||
0x00, // ParentalControlFlag = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[0] = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[1] = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlNext = 0
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginReplyMsgV1
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.LoginResponse != 0 {
|
||||
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||
}
|
||||
if packet.WorldName.Data != "Antonia" {
|
||||
t.Errorf("Expected WorldName='Antonia', got '%s'", packet.WorldName.Data)
|
||||
}
|
||||
if packet.AccountID != 54321 {
|
||||
t.Errorf("Expected AccountID=54321, got %d", packet.AccountID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginReplyMsgV284WithClassItems(t *testing.T) {
|
||||
data := []byte{
|
||||
0x00, // LoginResponse = 0
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||
0x00, // ParentalControlFlag = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||
0x31, 0xD4, 0x00, 0x00, // CacheSettingAccountID = 54321
|
||||
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||
0x00, // ResetAppearance = 0
|
||||
0x00, // DoNotForceSoga = 0
|
||||
0x00, 0x00, // Unknown5 = 0
|
||||
0x00, // Unknown6 = 0
|
||||
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||
0x00, 0x00, // Unknown8 (2 bytes)
|
||||
0x01, // Unknown10 = 1 (truthy, so class items will be parsed)
|
||||
0x01, // NumClassItems = 1
|
||||
// ClassItem 1
|
||||
0x05, // ClassID = 5
|
||||
0x01, // NumItems = 1
|
||||
// StartingItem 1
|
||||
0x64, 0x00, // ModelID = 100
|
||||
0x01, // SlotID = 1
|
||||
0x01, // UseColor = 1
|
||||
0x01, // UseHighlightColor = 1
|
||||
0xFF, 0x00, 0x00, // ModelColor = Red
|
||||
0x00, 0xFF, 0x00, // ModelHighlightColor = Green
|
||||
0x00, // UnknownArray2Size = 0
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginReplyMsgV284
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.LoginResponse != 0 {
|
||||
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||
}
|
||||
if packet.CacheSettingAccountID != 54321 {
|
||||
t.Errorf("Expected CacheSettingAccountID=54321, got %d", packet.CacheSettingAccountID)
|
||||
}
|
||||
if packet.Unknown10 != 1 {
|
||||
t.Errorf("Expected Unknown10=1, got %d", packet.Unknown10)
|
||||
}
|
||||
if packet.NumClassItems != 1 {
|
||||
t.Errorf("Expected NumClassItems=1, got %d", packet.NumClassItems)
|
||||
}
|
||||
if len(packet.ClassItems) != 1 {
|
||||
t.Errorf("Expected 1 class item, got %d", len(packet.ClassItems))
|
||||
}
|
||||
if packet.ClassItems[0].ClassID != 5 {
|
||||
t.Errorf("Expected ClassID=5, got %d", packet.ClassItems[0].ClassID)
|
||||
}
|
||||
if len(packet.ClassItems[0].StartingItems) != 1 {
|
||||
t.Errorf("Expected 1 starting item, got %d", len(packet.ClassItems[0].StartingItems))
|
||||
}
|
||||
if packet.ClassItems[0].StartingItems[0].ModelID != 100 {
|
||||
t.Errorf("Expected ModelID=100, got %d", packet.ClassItems[0].StartingItems[0].ModelID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginReplyMsgV284WithoutClassItems(t *testing.T) {
|
||||
data := []byte{
|
||||
0x00, // LoginResponse = 0
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||
0x00, // ParentalControlFlag = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||
0x31, 0xD4, 0x00, 0x00, // CacheSettingAccountID = 54321
|
||||
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||
0x00, // ResetAppearance = 0
|
||||
0x00, // DoNotForceSoga = 0
|
||||
0x00, 0x00, // Unknown5 = 0
|
||||
0x00, // Unknown6 = 0
|
||||
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||
0x00, 0x00, // Unknown8 (2 bytes)
|
||||
0x00, // Unknown10 = 0 (falsy, so class items will be skipped)
|
||||
0x00, // UnknownArray2Size = 0
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginReplyMsgV284
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.Unknown10 != 0 {
|
||||
t.Errorf("Expected Unknown10=0, got %d", packet.Unknown10)
|
||||
}
|
||||
if packet.NumClassItems != 0 {
|
||||
t.Errorf("Expected NumClassItems=0 (should be skipped), got %d", packet.NumClassItems)
|
||||
}
|
||||
if len(packet.ClassItems) != 0 {
|
||||
t.Errorf("Expected 0 class items (should be skipped), got %d", len(packet.ClassItems))
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionRegistryWithLoginReplyMsg(t *testing.T) {
|
||||
registry := parser.NewVersionRegistry()
|
||||
RegisterLoginServerStructs(registry)
|
||||
|
||||
// Test data for LoginReplyMsgV1
|
||||
data := []byte{
|
||||
0x00, // LoginResponse = 0
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // WorldName = "Antonia"
|
||||
0x00, // ParentalControlFlag = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[0] = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer[1] = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlNext = 0
|
||||
0x31, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
result, err := parser.ParseWithVersion(registry, "LoginReplyMsg", "1")
|
||||
if err != nil {
|
||||
t.Fatalf("Parse with version error: %v", err)
|
||||
}
|
||||
|
||||
packet, ok := result.(LoginReplyMsgV1)
|
||||
if !ok {
|
||||
t.Fatal("Expected LoginReplyMsgV1 type")
|
||||
}
|
||||
|
||||
if packet.LoginResponse != 0 {
|
||||
t.Errorf("Expected LoginResponse=0, got %d", packet.LoginResponse)
|
||||
}
|
||||
if packet.WorldName.Data != "Antonia" {
|
||||
t.Errorf("Expected WorldName='Antonia', got '%s'", packet.WorldName.Data)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVersionRegistryFallback(t *testing.T) {
|
||||
registry := parser.NewVersionRegistry()
|
||||
RegisterLoginServerStructs(registry)
|
||||
|
||||
data := []byte{
|
||||
0x39, 0x30, 0x00, 0x00, // CharID = 12345
|
||||
0x08, 0x00, 'T', 'e', 's', 't', 'C', 'h', 'a', 'r', // Name = "TestChar"
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
|
||||
// Request version 150 (doesn't exist), should fall back to version 1
|
||||
result, err := parser.ParseWithVersion(registry, "PlayRequest", "150")
|
||||
if err != nil {
|
||||
t.Fatalf("Parse with fallback error: %v", err)
|
||||
}
|
||||
|
||||
// Should get PlayRequestV1 (nearest lower version)
|
||||
packet, ok := result.(PlayRequestV1)
|
||||
if !ok {
|
||||
t.Error("Expected fallback to PlayRequestV1")
|
||||
}
|
||||
|
||||
if packet.CharID != 12345 {
|
||||
t.Errorf("Expected CharID=12345, got %d", packet.CharID)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWorldUpdate(t *testing.T) {
|
||||
data := []byte{
|
||||
0x01, 0x00, 0x00, 0x00, // ServerID = 1
|
||||
0x01, // Up = 1
|
||||
0x00, // Locked = 0
|
||||
0x00, // Unknown1 = 0
|
||||
0x32, // Unknown2 = 50
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet WorldUpdate
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
if packet.ServerID != 1 {
|
||||
t.Errorf("Expected ServerID=1, got %d", packet.ServerID)
|
||||
}
|
||||
if packet.Up != 1 {
|
||||
t.Errorf("Expected Up=1, got %d", packet.Up)
|
||||
}
|
||||
if packet.Locked != 0 {
|
||||
t.Errorf("Expected Locked=0, got %d", packet.Locked)
|
||||
}
|
||||
}
|
||||
|
||||
func TestLoginResponseV60100WithComplexArrays(t *testing.T) {
|
||||
data := []byte{
|
||||
0x00, // LoginResponse = 0
|
||||
0x07, 0x00, 'A', 'n', 't', 'o', 'n', 'i', 'a', // Unknown = "Antonia"
|
||||
0x00, // ParentalControlFlag = 0
|
||||
0x00, 0x00, 0x00, 0x00, // ParentalControlTimer = 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown2 (8 bytes)
|
||||
0x21, 0xD4, 0x00, 0x00, // AccountID = 54321
|
||||
0x04, 0x00, 't', 'e', 's', 't', // Unknown3 = "test"
|
||||
0x00, // ResetAppearance = 0
|
||||
0x00, // DoNotForceSoga = 0
|
||||
0x00, // Unknown4 = 0
|
||||
0x00, 0x00, // Unknown5 = 0
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, // Unknown6 (5 bytes)
|
||||
0x00, 0x00, 0x00, 0x00, // Unknown7 = 0
|
||||
0x00, 0x00, // Unknown7a = 0
|
||||
0x00, // RaceUnknown = 0
|
||||
0x00, 0x00, 0x00, // Unknown8 (3 bytes)
|
||||
0x00, 0x00, 0x00, // Unknown9 (3 bytes)
|
||||
0x01, // Unknown10 = 1 (enables class items)
|
||||
0x01, // NumClassItems = 1
|
||||
// ClassItem 1
|
||||
0x05, // ClassID = 5
|
||||
0x01, // NumItems = 1
|
||||
// StartingItem 1
|
||||
0x64, 0x00, 0x00, 0x00, // ModelID = 100 (int32 in newer versions)
|
||||
0x01, // SlotID = 1
|
||||
0x01, // UseColor = 1
|
||||
0x01, // UseHighlightColor = 1
|
||||
0xFF, 0x00, 0x00, // ModelColor = Red
|
||||
0x00, 0xFF, 0x00, // ModelHighlightColor = Green
|
||||
0x00, // UnknownArray2Size = 0
|
||||
0x00, 0x00, 0x00, 0x00, // Unknown11 = 0
|
||||
0x00, 0x00, 0x00, 0x00, // SubLevel = 0
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // RaceFlag = 0xFFFFFFFF
|
||||
0xFF, 0xFF, 0xFF, 0xFF, // ClassFlag = 0xFFFFFFFF
|
||||
0x08, 0x00, 't', 'e', 's', 't', 'p', 'a', 's', 's', // Password = "testpass"
|
||||
0x08, 0x00, 't', 'e', 's', 't', 'u', 's', 'e', 'r', // Username = "testuser"
|
||||
0x07, 0x00, 's', 'e', 'r', 'v', 'i', 'c', 'e', // Service = "service"
|
||||
0x01, // Unknown12 = 1 (enables Lvl90 class items)
|
||||
0x01, // Lvl90NumClassItems = 1
|
||||
// Lvl90 ClassItem 1
|
||||
0x06, // ClassID = 6
|
||||
0x01, // NumItems = 1
|
||||
// StartingItem 1
|
||||
0x65, 0x00, 0x00, 0x00, // ModelID = 101
|
||||
0x02, // SlotID = 2
|
||||
0x01, // UseColor = 1
|
||||
0x01, // UseHighlightColor = 1
|
||||
0x00, 0xFF, 0x00, // ModelColor = Green
|
||||
0xFF, 0x00, 0x00, // ModelHighlightColor = Red
|
||||
0x01, // Unknown13 = 1 (enables TimeLocked class items)
|
||||
0x01, // TimeLockedNumClassItems = 1
|
||||
// TimeLocked ClassItem 1
|
||||
0x07, // ClassID = 7
|
||||
0x01, // NumItems = 1
|
||||
// StartingItem 1
|
||||
0x66, 0x00, 0x00, 0x00, // ModelID = 102
|
||||
0x03, // SlotID = 3
|
||||
0x00, // UseColor = 0
|
||||
0x00, // UseHighlightColor = 0
|
||||
0x80, 0x80, 0x80, // ModelColor = Gray
|
||||
0x40, 0x40, 0x40, // ModelHighlightColor = Dark gray
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Unknown14 (13 bytes)
|
||||
}
|
||||
|
||||
parser := parser.NewParser(data)
|
||||
var packet LoginResponseV60100
|
||||
err := parser.ParseStruct(&packet)
|
||||
if err != nil {
|
||||
t.Fatalf("Parse error: %v", err)
|
||||
}
|
||||
|
||||
// Test main class items
|
||||
if len(packet.ClassItems) != 1 {
|
||||
t.Errorf("Expected 1 class item, got %d", len(packet.ClassItems))
|
||||
}
|
||||
if packet.ClassItems[0].ClassID != 5 {
|
||||
t.Errorf("Expected ClassID=5, got %d", packet.ClassItems[0].ClassID)
|
||||
}
|
||||
|
||||
// Test Lvl90 class items
|
||||
if len(packet.Lvl90ClassItems) != 1 {
|
||||
t.Errorf("Expected 1 Lvl90 class item, got %d", len(packet.Lvl90ClassItems))
|
||||
}
|
||||
if packet.Lvl90ClassItems[0].ClassID != 6 {
|
||||
t.Errorf("Expected Lvl90 ClassID=6, got %d", packet.Lvl90ClassItems[0].ClassID)
|
||||
}
|
||||
|
||||
// Test TimeLocked class items
|
||||
if len(packet.TimeLockedClassItems) != 1 {
|
||||
t.Errorf("Expected 1 TimeLocked class item, got %d", len(packet.TimeLockedClassItems))
|
||||
}
|
||||
if packet.TimeLockedClassItems[0].ClassID != 7 {
|
||||
t.Errorf("Expected TimeLocked ClassID=7, got %d", packet.TimeLockedClassItems[0].ClassID)
|
||||
}
|
||||
|
||||
if packet.RaceFlag != 0xFFFFFFFF {
|
||||
t.Errorf("Expected RaceFlag=0xFFFFFFFF, got %d", packet.RaceFlag)
|
||||
}
|
||||
}
|
@ -1,250 +0,0 @@
|
||||
# EQ2 Packet Parser
|
||||
|
||||
A dead-simple way to turn EverQuest 2's binary packet data into Go structs. Just add some tags to your struct fields and let reflection do the heavy lifting.
|
||||
|
||||
## How it works
|
||||
|
||||
```go
|
||||
// Your packet structure
|
||||
type LoginPacket struct {
|
||||
UserID uint32 `eq2:"int32"`
|
||||
Username common.EQ2String16 `eq2:"string16"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// Parse some bytes
|
||||
data := []byte{...} // whatever bytes you got
|
||||
parser := parser.NewParser(data)
|
||||
|
||||
var packet LoginPacket
|
||||
err := parser.ParseStruct(&packet)
|
||||
// boom, packet is now filled with data
|
||||
```
|
||||
|
||||
## Tag Syntax
|
||||
|
||||
Just slap `eq2:"type,options"` on your fields and you're good to go.
|
||||
|
||||
### The usual suspects
|
||||
```go
|
||||
PlayerID uint32 `eq2:"int32"` // 32-bit integer
|
||||
Health uint16 `eq2:"int16"` // 16-bit integer
|
||||
Alive uint8 `eq2:"int8"` // 8-bit integer
|
||||
Damage float32 `eq2:"float"` // 32-bit float
|
||||
Name common.EQ2String16 `eq2:"string16"` // EQ2's weird string format
|
||||
Color common.EQ2Color `eq2:"color"` // RGB color
|
||||
```
|
||||
|
||||
### Arrays (because everything's an array in EQ2)
|
||||
```go
|
||||
// Fixed size - always 5 items
|
||||
Stats []uint16 `eq2:"int16,len=5"`
|
||||
|
||||
// Dynamic size - read ItemCount first, then that many items
|
||||
ItemCount uint8 `eq2:"int8"`
|
||||
Items []Item `eq2:"array,arraysize=ItemCount"`
|
||||
```
|
||||
|
||||
### Conditionals (the fun stuff)
|
||||
```go
|
||||
// Only parse this if Channel equals 1
|
||||
MessageType uint8 `eq2:"int8,if=Channel==1"`
|
||||
|
||||
// Only parse if HasRewards is truthy
|
||||
HasRewards uint8 `eq2:"int8"`
|
||||
RewardData *RewardInfo `eq2:"substruct,ifvariableset=HasRewards"`
|
||||
|
||||
// Only parse if we set the "has_equipment" flag
|
||||
Equipment []Equipment `eq2:"equipment,ifflag=has_equipment"`
|
||||
|
||||
// Array index variables - access specific array elements
|
||||
ModCount uint8 `eq2:"int8"`
|
||||
Mods []Mod `eq2:"array,arraysize=ModCount"`
|
||||
// This checks if Mods[0] exists and is truthy
|
||||
ExtraData []byte `eq2:"char,len=10,ifvariableset=header_info_mod_need_0"`
|
||||
|
||||
// Dynamic array index using %i (replaced with current array index)
|
||||
StatTypes []uint8 `eq2:"int8,len=5"`
|
||||
StatValues []any `eq2:"int32,type2=float,type2criteria=stat_type_%i!=6"`
|
||||
```
|
||||
|
||||
### Comma-separated conditions
|
||||
Multiple variables can be checked in a single condition using comma-separated lists:
|
||||
|
||||
```go
|
||||
// Parse only if NONE of the listed variables are set
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0,header_unknown_0"`
|
||||
|
||||
// Parse if ANY of the listed variables are set
|
||||
BonusData []byte `eq2:"char,len=20,ifvariableset=has_bonus,has_special,has_extra"`
|
||||
|
||||
// Parse if ANY of the listed flags are set
|
||||
OptionalField uint32 `eq2:"int32,ifflag=debug_mode,test_mode,dev_mode"`
|
||||
|
||||
// Parse if ALL of the listed flags are NOT set
|
||||
ProductionData []byte `eq2:"char,len=50,ifflagnotset=debug_mode,test_mode"`
|
||||
|
||||
// Multiple equals conditions (ANY must be true)
|
||||
TypeData any `eq2:"int32,ifequals=type=1,category=special"`
|
||||
|
||||
// Multiple not-equals conditions (ALL must be true)
|
||||
Value uint16 `eq2:"int16,ifnotequals=status=disabled,flag=hidden"`
|
||||
```
|
||||
|
||||
**Comma-separated logic rules:**
|
||||
- `ifvariableset` - TRUE if ANY variable is set
|
||||
- `ifvariablenotset` - TRUE if ALL variables are NOT set
|
||||
- `ifflag` - TRUE if ANY flag is set
|
||||
- `ifflagnotset` - TRUE if ALL flags are NOT set
|
||||
- `ifequals` - TRUE if ANY condition matches
|
||||
- `ifnotequals` - TRUE if ALL conditions are true (none match)
|
||||
|
||||
### Type switching (when EQ2 reuses the same bytes for different things)
|
||||
```go
|
||||
// Normally parse as int32, but if StatType != 6, parse as float instead
|
||||
StatType uint8 `eq2:"int8"`
|
||||
StatValue any `eq2:"int32,type2=float,type2criteria=StatType!=6"`
|
||||
|
||||
// String length operators for type switching
|
||||
NameLength uint8 `eq2:"int8"`
|
||||
Name string `eq2:"string16,type2=string8,type2criteria=stat_name!>10"`
|
||||
```
|
||||
|
||||
### String length operators
|
||||
Use `!>`, `!<`, `!>=`, `!<=`, `!=` for string length comparisons:
|
||||
```go
|
||||
// Switch to string8 if name length > 10 characters
|
||||
Name string `eq2:"string16,type2=string8,type2criteria=player_name!>10"`
|
||||
|
||||
// Only parse if description is not empty
|
||||
HasDesc uint8 `eq2:"int8"`
|
||||
Description string `eq2:"string16,ifvariableset=HasDesc,if=description!>0"`
|
||||
```
|
||||
|
||||
### Size limits (because EQ2 packets can get weird)
|
||||
```go
|
||||
// If the data is bigger than 1000 bytes, just truncate it
|
||||
DataSize uint16 `eq2:"int16"`
|
||||
Data []byte `eq2:"char,len=DataSize,maxsize=1000,skipoversized"`
|
||||
```
|
||||
|
||||
## Multiple client versions
|
||||
|
||||
EQ2 has like 50 different client versions, each with slightly different packet layouts. Handle it like this:
|
||||
|
||||
```go
|
||||
registry := parser.NewVersionRegistry()
|
||||
registry.RegisterStruct("LoginReply", "1.0", reflect.TypeOf(LoginReplyV1{}))
|
||||
registry.RegisterStruct("LoginReply", "2.0", reflect.TypeOf(LoginReplyV2{}))
|
||||
|
||||
// Parser picks the right version (or falls back to closest match)
|
||||
result, err := parser.ParseWithVersion(registry, "LoginReply", clientVersion)
|
||||
```
|
||||
|
||||
## Real example
|
||||
|
||||
```go
|
||||
type CharacterData struct {
|
||||
// Basic stuff
|
||||
CharID uint32 `eq2:"int32"`
|
||||
Name common.EQ2String16 `eq2:"string16"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
|
||||
// Guild info (only if they're in a guild)
|
||||
HasGuild uint8 `eq2:"int8"`
|
||||
GuildID uint32 `eq2:"int32,ifvariableset=HasGuild"`
|
||||
|
||||
// Variable number of items
|
||||
ItemCount uint16 `eq2:"int16"`
|
||||
Items []InventoryItem `eq2:"array,arraysize=ItemCount"`
|
||||
|
||||
// Nested stuff
|
||||
Stats PlayerStats `eq2:"substruct"`
|
||||
|
||||
// Array index access example
|
||||
BuffCount uint8 `eq2:"int8"`
|
||||
Buffs []BuffData `eq2:"array,arraysize=BuffCount"`
|
||||
// Only parse extended data if first buff exists
|
||||
ExtendedBuffData []byte `eq2:"char,len=20,ifvariableset=buffs_0"`
|
||||
|
||||
// Comma-separated conditions example
|
||||
HeaderFlags uint8 `eq2:"int8"`
|
||||
// Parse effects only if neither unknown field is set
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0,header_unknown_0"`
|
||||
Effects []EffectData `eq2:"array,arraysize=NumEffects"`
|
||||
}
|
||||
|
||||
type InventoryItem struct {
|
||||
ItemID uint32 `eq2:"int32"`
|
||||
Quantity uint16 `eq2:"int16"`
|
||||
Color common.EQ2Color `eq2:"color"`
|
||||
|
||||
// Type switching based on string length
|
||||
NameType uint8 `eq2:"int8"`
|
||||
Name any `eq2:"string16,type2=string8,type2criteria=item_name!<=8"`
|
||||
}
|
||||
|
||||
type PlayerStats struct {
|
||||
Health uint32 `eq2:"int32"`
|
||||
Mana uint32 `eq2:"int32"`
|
||||
Stamina uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
type BuffData struct {
|
||||
BuffID uint32 `eq2:"int32"`
|
||||
Duration uint16 `eq2:"int16"`
|
||||
}
|
||||
|
||||
type EffectData struct {
|
||||
Effect common.EQ2String16 `eq2:"string16"`
|
||||
Percentage uint8 `eq2:"int8"`
|
||||
}
|
||||
```
|
||||
|
||||
## Advanced conditional patterns
|
||||
|
||||
```go
|
||||
type ComplexPacket struct {
|
||||
// Array with per-element conditionals using %i
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatTypes []uint8 `eq2:"int8,len=StatCount"`
|
||||
StatValues []any `eq2:"int32,type2=float,type2criteria=stat_type_%i!=6"`
|
||||
|
||||
// Array index access for conditionals
|
||||
ModCount uint8 `eq2:"int8"`
|
||||
Mods []Mod `eq2:"array,arraysize=ModCount"`
|
||||
// Parse only if specific array elements exist
|
||||
Bonus1 uint32 `eq2:"int32,ifvariableset=header_info_mod_need_0"`
|
||||
Bonus2 uint32 `eq2:"int32,ifvariableset=header_info_mod_need_1"`
|
||||
|
||||
// String length conditionals
|
||||
PlayerName string `eq2:"string16"`
|
||||
ShortName string `eq2:"string8,if=player_name!<=8"`
|
||||
LongDesc string `eq2:"string32,if=player_name!>15"`
|
||||
|
||||
// Comma-separated multi-condition examples
|
||||
DebugInfo []byte `eq2:"char,len=100,ifflag=debug_mode,test_mode,dev_mode"`
|
||||
ProdData []byte `eq2:"char,len=50,ifflagnotset=debug_mode,test_mode,dev_mode"`
|
||||
|
||||
// Multiple variable checks
|
||||
OptionalData []byte `eq2:"char,len=20,ifvariableset=has_optional,has_extended"`
|
||||
CleanupData []byte `eq2:"char,len=10,ifvariablenotset=dirty_flag,temp_flag,cache_flag"`
|
||||
}
|
||||
```
|
||||
|
||||
## Converting from XML
|
||||
|
||||
If you've got EQ2's XML packet definitions, the conversion is pretty straightforward:
|
||||
|
||||
| XML | Go Tag |
|
||||
|-----|--------|
|
||||
| `Type="int32"` | `eq2:"int32"` |
|
||||
| `ArraySizeVariable="count"` | `arraysize=Count` |
|
||||
| `IfVariableSet="flag"` | `ifvariableset=Flag` |
|
||||
| `IfVariableNotSet="var1,var2"` | `ifvariablenotset=var1,var2` |
|
||||
| `IfFlag="flag1,flag2"` | `ifflag=flag1,flag2` |
|
||||
| `Size="5"` | `len=5` |
|
||||
| `Type2Criteria="field!=value"` | `type2criteria=Field!=value` |
|
||||
| `Type2Criteria="name!>10"` | `type2criteria=name!>10` |
|
||||
| Array index access | `ifvariableset=array_name_0` |
|
||||
| Dynamic index patterns | `type2criteria=field_%i!=value` |
|
@ -1,214 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// readArray handles array parsing with full substruct support
|
||||
func (p *Parser) readArray(field reflect.Value, fieldTag *FieldTag) error {
|
||||
var arraySize int
|
||||
if fieldTag.ArraySizeVar != "" {
|
||||
arraySize = p.getDynamicLength(fieldTag.ArraySizeVar)
|
||||
} else {
|
||||
size, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
arraySize = int(size)
|
||||
}
|
||||
|
||||
if arraySize == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
if field.Kind() == reflect.Slice {
|
||||
elemType := field.Type().Elem()
|
||||
slice := reflect.MakeSlice(field.Type(), arraySize, arraySize)
|
||||
|
||||
p.arrayStack = append(p.arrayStack, ArrayContext{
|
||||
elementType: elemType,
|
||||
totalSize: arraySize,
|
||||
sizeVariable: fieldTag.ArraySizeVar,
|
||||
})
|
||||
|
||||
for i := 0; i < arraySize; i++ {
|
||||
p.arrayStack[len(p.arrayStack)-1].currentIndex = i
|
||||
elem := slice.Index(i)
|
||||
|
||||
if elemType.Kind() == reflect.Struct {
|
||||
if err := p.parseStructElement(elem, elemType); err != nil {
|
||||
p.arrayStack = p.arrayStack[:len(p.arrayStack)-1]
|
||||
return fmt.Errorf("array element %d: %w", i, err)
|
||||
}
|
||||
} else {
|
||||
if err := p.readPrimitiveArrayElement(elem, elemType); err != nil {
|
||||
p.arrayStack = p.arrayStack[:len(p.arrayStack)-1]
|
||||
return fmt.Errorf("array element %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
p.arrayStack = p.arrayStack[:len(p.arrayStack)-1]
|
||||
field.Set(slice)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// readSubstruct handles substruct parsing
|
||||
func (p *Parser) readSubstruct(field reflect.Value, length int) error {
|
||||
if field.Kind() == reflect.Slice {
|
||||
elemType := field.Type().Elem()
|
||||
slice := reflect.MakeSlice(field.Type(), length, length)
|
||||
|
||||
for i := range length {
|
||||
elem := slice.Index(i)
|
||||
if err := p.parseStructElement(elem, elemType); err != nil {
|
||||
return fmt.Errorf("substruct element %d: %w", i, err)
|
||||
}
|
||||
}
|
||||
|
||||
field.Set(slice)
|
||||
return nil
|
||||
} else if field.Kind() == reflect.Struct {
|
||||
return p.parseStructElement(field, field.Type())
|
||||
} else if field.Kind() == reflect.Ptr && field.Type().Elem().Kind() == reflect.Struct {
|
||||
structType := field.Type().Elem()
|
||||
newStruct := reflect.New(structType)
|
||||
if err := p.parseStructElement(newStruct.Elem(), structType); err != nil {
|
||||
return err
|
||||
}
|
||||
field.Set(newStruct)
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("substruct field must be struct, slice of structs, or pointer to struct")
|
||||
}
|
||||
|
||||
// parseStructElement parses a single struct element
|
||||
func (p *Parser) parseStructElement(elem reflect.Value, elemType reflect.Type) error {
|
||||
oldStruct := p.currentStruct
|
||||
oldCache := p.fieldCache
|
||||
|
||||
p.currentStruct = elem
|
||||
p.fieldCache = make(map[string]any)
|
||||
p.structStack = append(p.structStack, elem)
|
||||
|
||||
for i := range elem.NumField() {
|
||||
field := elem.Field(i)
|
||||
fieldType := elemType.Field(i)
|
||||
|
||||
if !field.CanSet() {
|
||||
continue
|
||||
}
|
||||
|
||||
tag := fieldType.Tag.Get("eq2")
|
||||
if tag == "" || tag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := p.parseField(field, tag); err != nil {
|
||||
p.structStack = p.structStack[:len(p.structStack)-1]
|
||||
p.currentStruct = oldStruct
|
||||
p.fieldCache = oldCache
|
||||
return fmt.Errorf("field %s: %w", fieldType.Name, err)
|
||||
}
|
||||
|
||||
if field.CanInterface() {
|
||||
p.fieldCache[fieldType.Name] = field.Interface()
|
||||
}
|
||||
}
|
||||
|
||||
p.structStack = p.structStack[:len(p.structStack)-1]
|
||||
p.currentStruct = oldStruct
|
||||
p.fieldCache = oldCache
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// readPrimitiveArrayElement reads primitive array elements
|
||||
func (p *Parser) readPrimitiveArrayElement(elem reflect.Value, elemType reflect.Type) error {
|
||||
switch elemType.Kind() {
|
||||
case reflect.Uint8:
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetUint(uint64(val))
|
||||
case reflect.Uint16:
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetUint(uint64(val))
|
||||
case reflect.Uint32:
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetUint(uint64(val))
|
||||
case reflect.Uint64:
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetUint(val)
|
||||
case reflect.Int8:
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetInt(int64(int8(val)))
|
||||
case reflect.Int16:
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetInt(int64(int16(val)))
|
||||
case reflect.Int32:
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetInt(int64(int32(val)))
|
||||
case reflect.Int64:
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetInt(int64(val))
|
||||
case reflect.Float32:
|
||||
val, err := p.readFloat32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetFloat(float64(val))
|
||||
case reflect.Float64:
|
||||
val, err := p.readFloat64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
elem.SetFloat(val)
|
||||
default:
|
||||
return fmt.Errorf("unsupported primitive array element type: %v", elemType.Kind())
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetCurrentArrayIndex returns current array index for nested parsing
|
||||
func (p *Parser) GetCurrentArrayIndex() int {
|
||||
if len(p.arrayStack) > 0 {
|
||||
return p.arrayStack[len(p.arrayStack)-1].currentIndex
|
||||
}
|
||||
return -1
|
||||
}
|
||||
|
||||
// GetCurrentArraySize returns current array size
|
||||
func (p *Parser) GetCurrentArraySize() int {
|
||||
if len(p.arrayStack) > 0 {
|
||||
return p.arrayStack[len(p.arrayStack)-1].totalSize
|
||||
}
|
||||
return 0
|
||||
}
|
@ -1,355 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// evaluateAllConditions checks all conditional logic
|
||||
func (p *Parser) evaluateAllConditions(fieldTag *FieldTag, _ reflect.Value) bool {
|
||||
if fieldTag.Condition != nil && !p.evaluateCondition(fieldTag.Condition) {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldTag.IfVariableSet != "" && !p.evaluateVariableSetCondition(fieldTag.IfVariableSet) {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldTag.IfVariableNotSet != "" && !p.evaluateVariableNotSetCondition(fieldTag.IfVariableNotSet) {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldTag.IfFlag != "" && !p.evaluateFlagCondition(fieldTag.IfFlag) {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldTag.IfFlagNotSet != "" && !p.evaluateFlagNotSetCondition(fieldTag.IfFlagNotSet) {
|
||||
return false
|
||||
}
|
||||
|
||||
if fieldTag.IfEquals != "" {
|
||||
if !p.evaluateEqualsConditions(fieldTag.IfEquals) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
if fieldTag.IfNotEquals != "" {
|
||||
if !p.evaluateNotEqualsConditions(fieldTag.IfNotEquals) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// evaluateVariableSetCondition handles comma-separated variable set conditions
|
||||
func (p *Parser) evaluateVariableSetCondition(variables string) bool {
|
||||
varList := p.splitCommaSeparated(variables)
|
||||
// Return true if ANY variable is set
|
||||
for _, variable := range varList {
|
||||
if p.isVariableSet(variable) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// evaluateVariableNotSetCondition handles comma-separated variable not set conditions
|
||||
func (p *Parser) evaluateVariableNotSetCondition(variables string) bool {
|
||||
varList := p.splitCommaSeparated(variables)
|
||||
// Return true if ALL variables are not set
|
||||
for _, variable := range varList {
|
||||
if p.isVariableSet(variable) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// evaluateFlagCondition handles comma-separated flag conditions
|
||||
func (p *Parser) evaluateFlagCondition(flags string) bool {
|
||||
flagList := p.splitCommaSeparated(flags)
|
||||
// Return true if ANY flag is set
|
||||
for _, flag := range flagList {
|
||||
if p.flags[flag] {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// evaluateFlagNotSetCondition handles comma-separated flag not set conditions
|
||||
func (p *Parser) evaluateFlagNotSetCondition(flags string) bool {
|
||||
flagList := p.splitCommaSeparated(flags)
|
||||
// Return true if ALL flags are not set
|
||||
for _, flag := range flagList {
|
||||
if p.flags[flag] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// evaluateEqualsConditions handles comma-separated equals conditions
|
||||
func (p *Parser) evaluateEqualsConditions(conditions string) bool {
|
||||
conditionList := p.splitCommaSeparated(conditions)
|
||||
// Return true if ANY condition is true
|
||||
for _, condition := range conditionList {
|
||||
parts := strings.Split(condition, "=")
|
||||
if len(parts) == 2 && p.evaluateEqualsCondition(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// evaluateNotEqualsConditions handles comma-separated not equals conditions
|
||||
func (p *Parser) evaluateNotEqualsConditions(conditions string) bool {
|
||||
conditionList := p.splitCommaSeparated(conditions)
|
||||
// Return true if ALL conditions are true (all not equal)
|
||||
for _, condition := range conditionList {
|
||||
parts := strings.Split(condition, "=")
|
||||
if len(parts) == 2 {
|
||||
if p.evaluateEqualsCondition(strings.TrimSpace(parts[0]), strings.TrimSpace(parts[1])) {
|
||||
return false // This condition is false (they are equal)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// splitCommaSeparated splits a comma-separated string and trims whitespace
|
||||
func (p *Parser) splitCommaSeparated(input string) []string {
|
||||
if input == "" {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
parts := strings.Split(input, ",")
|
||||
result := make([]string, len(parts))
|
||||
for i, part := range parts {
|
||||
result[i] = strings.TrimSpace(part)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// evaluateCondition evaluates conditions for conditional fields
|
||||
func (p *Parser) evaluateCondition(condition *FieldCondition) bool {
|
||||
if condition.Type == "simple" {
|
||||
return p.isVariableSet(condition.Variable)
|
||||
}
|
||||
|
||||
cachedValue, exists := p.resolveVariable(condition.Variable)
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
compareValue, err := p.convertValue(condition.Value, cachedValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.compareValues(cachedValue, compareValue, condition.Operator)
|
||||
}
|
||||
|
||||
// isVariableSet checks if a variable exists and has a truthy value
|
||||
func (p *Parser) isVariableSet(variable string) bool {
|
||||
cachedValue, exists := p.resolveVariable(variable)
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
return p.isTruthy(cachedValue)
|
||||
}
|
||||
|
||||
// evaluateEqualsCondition checks field equality
|
||||
func (p *Parser) evaluateEqualsCondition(variable, value string) bool {
|
||||
cachedValue, exists := p.resolveVariable(variable)
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
compareValue, err := p.convertValue(value, cachedValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.compareValues(cachedValue, compareValue, "==")
|
||||
}
|
||||
|
||||
// evaluateType2Criteria evaluates type2 criteria for alternative types with string length support
|
||||
func (p *Parser) evaluateType2Criteria(criteria string) bool {
|
||||
// String length operators: !>, !<, !>=, !<=, !=
|
||||
stringLengthOps := []string{"!>=", "!<=", "!>", "!<", "!="}
|
||||
|
||||
for _, op := range stringLengthOps {
|
||||
if idx := strings.Index(criteria, op); idx > 0 {
|
||||
fieldName := strings.TrimSpace(criteria[:idx])
|
||||
valueStr := strings.TrimSpace(criteria[idx+len(op):])
|
||||
|
||||
cachedValue, exists := p.resolveVariable(fieldName)
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.evaluateStringLengthCondition(cachedValue, valueStr, op)
|
||||
}
|
||||
}
|
||||
|
||||
// Standard comparison operators
|
||||
operators := []string{">=", "<=", ">", "<", "=="}
|
||||
|
||||
for _, op := range operators {
|
||||
if idx := strings.Index(criteria, op); idx > 0 {
|
||||
fieldName := strings.TrimSpace(criteria[:idx])
|
||||
valueStr := strings.TrimSpace(criteria[idx+len(op):])
|
||||
|
||||
cachedValue, exists := p.resolveVariable(fieldName)
|
||||
if !exists {
|
||||
return false
|
||||
}
|
||||
|
||||
compareValue, err := p.convertValue(valueStr, cachedValue)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return p.compareValues(cachedValue, compareValue, op)
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// evaluateStringLengthCondition evaluates string length conditions
|
||||
func (p *Parser) evaluateStringLengthCondition(value any, lengthStr, operator string) bool {
|
||||
var stringVal string
|
||||
|
||||
// Extract string value from various types
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
stringVal = v
|
||||
default:
|
||||
// Try to get string representation from struct fields
|
||||
if reflect.TypeOf(value).Kind() == reflect.Struct {
|
||||
val := reflect.ValueOf(value)
|
||||
if dataField := val.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String {
|
||||
stringVal = dataField.String()
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
targetLength, err := strconv.Atoi(lengthStr)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
stringLength := len(stringVal)
|
||||
|
||||
switch operator {
|
||||
case "!>":
|
||||
return stringLength > targetLength
|
||||
case "!<":
|
||||
return stringLength < targetLength
|
||||
case "!>=":
|
||||
return stringLength >= targetLength
|
||||
case "!<=":
|
||||
return stringLength <= targetLength
|
||||
case "!=":
|
||||
return stringLength != targetLength
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// resolveVariable resolves variables with support for array indices and complex patterns
|
||||
func (p *Parser) resolveVariable(variable string) (any, bool) {
|
||||
// Handle %i patterns by replacing with current array index
|
||||
if strings.Contains(variable, "%i") {
|
||||
currentIndex := p.GetCurrentArrayIndex()
|
||||
if currentIndex >= 0 {
|
||||
variable = strings.ReplaceAll(variable, "%i", strconv.Itoa(currentIndex))
|
||||
}
|
||||
}
|
||||
|
||||
// Check field cache first
|
||||
if cachedValue, exists := p.fieldCache[variable]; exists {
|
||||
return cachedValue, true
|
||||
}
|
||||
|
||||
// Handle array index patterns like "header_info_mod_need_0"
|
||||
if strings.Contains(variable, "_") {
|
||||
if value, exists := p.resolveArrayIndexVariable(variable); exists {
|
||||
return value, true
|
||||
}
|
||||
}
|
||||
|
||||
// Check current struct
|
||||
if p.currentStruct.IsValid() {
|
||||
if field := p.currentStruct.FieldByName(variable); field.IsValid() {
|
||||
return field.Interface(), true
|
||||
}
|
||||
}
|
||||
|
||||
// Check struct stack for nested resolution
|
||||
for i := len(p.structStack) - 1; i >= 0; i-- {
|
||||
if field := p.structStack[i].FieldByName(variable); field.IsValid() {
|
||||
return field.Interface(), true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// resolveArrayIndexVariable handles variables with array index suffixes
|
||||
func (p *Parser) resolveArrayIndexVariable(variable string) (any, bool) {
|
||||
parts := strings.Split(variable, "_")
|
||||
if len(parts) < 2 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Try to extract index from last part
|
||||
lastPart := parts[len(parts)-1]
|
||||
if index, err := strconv.Atoi(lastPart); err == nil {
|
||||
// Reconstruct base variable name without index
|
||||
baseVar := strings.Join(parts[:len(parts)-1], "_")
|
||||
|
||||
// Look for array/slice field with this base name
|
||||
if cachedValue, exists := p.fieldCache[baseVar]; exists {
|
||||
return p.getArrayElement(cachedValue, index)
|
||||
}
|
||||
|
||||
// Check current struct for array field
|
||||
if p.currentStruct.IsValid() {
|
||||
if field := p.currentStruct.FieldByName(baseVar); field.IsValid() {
|
||||
return p.getArrayElement(field.Interface(), index)
|
||||
}
|
||||
}
|
||||
|
||||
// Check struct stack
|
||||
for i := len(p.structStack) - 1; i >= 0; i-- {
|
||||
if field := p.structStack[i].FieldByName(baseVar); field.IsValid() {
|
||||
return p.getArrayElement(field.Interface(), index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// getArrayElement safely extracts element from array/slice
|
||||
func (p *Parser) getArrayElement(value any, index int) (any, bool) {
|
||||
val := reflect.ValueOf(value)
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
if index >= 0 && index < val.Len() {
|
||||
return val.Index(index).Interface(), true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
417
internal/packets/parser/context.go
Normal file
417
internal/packets/parser/context.go
Normal file
@ -0,0 +1,417 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"eq2emu/internal/common"
|
||||
"strconv"
|
||||
"strings"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
type ParseContext struct {
|
||||
data []byte
|
||||
offset int
|
||||
version uint32
|
||||
flags uint64
|
||||
vars map[string]any
|
||||
arrayStack []int
|
||||
}
|
||||
|
||||
func NewContext(data []byte, version uint32, flags uint64) *ParseContext {
|
||||
return &ParseContext{
|
||||
data: data,
|
||||
version: version,
|
||||
flags: flags,
|
||||
vars: make(map[string]any),
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readUint8() uint8 {
|
||||
val := ctx.data[ctx.offset]
|
||||
ctx.offset++
|
||||
return val
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readUint16() uint16 {
|
||||
val := binary.LittleEndian.Uint16(ctx.data[ctx.offset:])
|
||||
ctx.offset += 2
|
||||
return val
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readUint32() uint32 {
|
||||
val := binary.LittleEndian.Uint32(ctx.data[ctx.offset:])
|
||||
ctx.offset += 4
|
||||
return val
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readUint64() uint64 {
|
||||
val := binary.LittleEndian.Uint64(ctx.data[ctx.offset:])
|
||||
ctx.offset += 8
|
||||
return val
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readOversizedUint8(threshold int) uint8 {
|
||||
if ctx.data[ctx.offset] == byte(threshold) {
|
||||
ctx.offset++
|
||||
return ctx.readUint8()
|
||||
}
|
||||
return ctx.readUint8()
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readOversizedUint16(threshold int) uint16 {
|
||||
if ctx.data[ctx.offset] == byte(threshold) {
|
||||
ctx.offset++
|
||||
return ctx.readUint16()
|
||||
}
|
||||
return uint16(ctx.readUint8())
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readOversizedUint32(threshold int) uint32 {
|
||||
if ctx.data[ctx.offset] == byte(threshold) {
|
||||
ctx.offset++
|
||||
return ctx.readUint32()
|
||||
}
|
||||
return uint32(ctx.readUint16())
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readString8() string {
|
||||
length := ctx.readUint8()
|
||||
str := string(ctx.data[ctx.offset : ctx.offset+int(length)])
|
||||
ctx.offset += int(length)
|
||||
return str
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readString16() string {
|
||||
length := ctx.readUint16()
|
||||
str := string(ctx.data[ctx.offset : ctx.offset+int(length)])
|
||||
ctx.offset += int(length)
|
||||
return str
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readEQ2String8() common.EQ2String8 {
|
||||
size := ctx.readUint8()
|
||||
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
||||
ctx.offset += int(size)
|
||||
return common.EQ2String8{
|
||||
Size: size,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readEQ2String16() common.EQ2String16 {
|
||||
size := ctx.readUint16()
|
||||
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
||||
ctx.offset += int(size)
|
||||
return common.EQ2String16{
|
||||
Size: size,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readEQ2String32() common.EQ2String32 {
|
||||
size := ctx.readUint32()
|
||||
data := string(ctx.data[ctx.offset : ctx.offset+int(size)])
|
||||
ctx.offset += int(size)
|
||||
return common.EQ2String32{
|
||||
Size: size,
|
||||
Data: data,
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readEQ2Color() common.EQ2Color {
|
||||
return common.EQ2Color{
|
||||
Red: ctx.readUint8(),
|
||||
Green: ctx.readUint8(),
|
||||
Blue: ctx.readUint8(),
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readEQ2Equipment() common.EQ2EquipmentItem {
|
||||
return common.EQ2EquipmentItem{
|
||||
Type: ctx.readUint16(),
|
||||
Color: ctx.readEQ2Color(),
|
||||
Highlight: ctx.readEQ2Color(),
|
||||
}
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readBytes(count int) []byte {
|
||||
val := make([]byte, count)
|
||||
copy(val, ctx.data[ctx.offset:ctx.offset+count])
|
||||
ctx.offset += count
|
||||
return val
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readFloat32() float32 {
|
||||
val := ctx.readUint32()
|
||||
return *(*float32)(unsafe.Pointer(&val))
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) readFloat64() float64 {
|
||||
val := ctx.readUint64()
|
||||
return *(*float64)(unsafe.Pointer(&val))
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) setVar(name string, value any) {
|
||||
ctx.vars[name] = value
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) pushArrayIndex(index int) {
|
||||
ctx.arrayStack = append(ctx.arrayStack, index)
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) popArrayIndex() {
|
||||
if len(ctx.arrayStack) > 0 {
|
||||
ctx.arrayStack = ctx.arrayStack[:len(ctx.arrayStack)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// Condition evaluation methods
|
||||
func (ctx *ParseContext) checkCondition(condition string) bool {
|
||||
if condition == "" {
|
||||
return true
|
||||
}
|
||||
|
||||
// Handle comma-separated OR conditions
|
||||
if strings.Contains(condition, ",") {
|
||||
parts := strings.Split(condition, ",")
|
||||
for _, part := range parts {
|
||||
if ctx.evaluateCondition(strings.TrimSpace(part)) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Handle AND conditions with &
|
||||
if strings.Contains(condition, "&") && !strings.Contains(condition, "0x") {
|
||||
parts := strings.Split(condition, "&")
|
||||
for _, part := range parts {
|
||||
if !ctx.evaluateCondition(strings.TrimSpace(part)) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
return ctx.evaluateCondition(condition)
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) evaluateCondition(condition string) bool {
|
||||
// Flag conditions: flag:name or !flag:name
|
||||
if strings.HasPrefix(condition, "flag:") {
|
||||
flagName := condition[5:]
|
||||
return (ctx.flags & ctx.getFlagValue(flagName)) != 0
|
||||
}
|
||||
if strings.HasPrefix(condition, "!flag:") {
|
||||
flagName := condition[6:]
|
||||
return (ctx.flags & ctx.getFlagValue(flagName)) == 0
|
||||
}
|
||||
|
||||
// Variable conditions: var:name or !var:name (with %i support)
|
||||
if strings.HasPrefix(condition, "var:") {
|
||||
varName := ctx.resolveVariableName(condition[4:])
|
||||
return ctx.hasVar(varName)
|
||||
}
|
||||
if strings.HasPrefix(condition, "!var:") {
|
||||
varName := ctx.resolveVariableName(condition[5:])
|
||||
return !ctx.hasVar(varName)
|
||||
}
|
||||
|
||||
// Version comparisons
|
||||
if strings.HasPrefix(condition, "version") {
|
||||
return ctx.evaluateVersionCondition(condition)
|
||||
}
|
||||
|
||||
// Bitwise AND: header_flag&0x01 (with %i support)
|
||||
if strings.Contains(condition, "&0x") {
|
||||
parts := strings.SplitN(condition, "&", 2)
|
||||
varName := ctx.resolveVariableName(parts[0])
|
||||
hexValue, _ := strconv.ParseUint(parts[1], 0, 64)
|
||||
varValue := ctx.getVarValue(varName)
|
||||
return (varValue & hexValue) != 0
|
||||
}
|
||||
|
||||
// String length operators: name!>5, name!<=10 (with %i support)
|
||||
stringOps := []string{"!>=", "!<=", "!>", "!<", "!="}
|
||||
for _, op := range stringOps {
|
||||
if idx := strings.Index(condition, op); idx > 0 {
|
||||
varName := ctx.resolveVariableName(condition[:idx])
|
||||
valueStr := condition[idx+len(op):]
|
||||
return ctx.evaluateStringLength(varName, valueStr, op)
|
||||
}
|
||||
}
|
||||
|
||||
// Comparison operators: >=, <=, >, <, ==, != (with %i support)
|
||||
compOps := []string{">=", "<=", ">", "<", "==", "!="}
|
||||
for _, op := range compOps {
|
||||
if idx := strings.Index(condition, op); idx > 0 {
|
||||
varName := ctx.resolveVariableName(condition[:idx])
|
||||
valueStr := condition[idx+len(op):]
|
||||
return ctx.evaluateComparison(varName, valueStr, op)
|
||||
}
|
||||
}
|
||||
|
||||
// Simple variable existence (with %i support)
|
||||
resolvedName := ctx.resolveVariableName(condition)
|
||||
return ctx.hasVar(resolvedName)
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) evaluateVersionCondition(condition string) bool {
|
||||
if strings.Contains(condition, ">=") {
|
||||
versionStr := condition[strings.Index(condition, ">=")+2:]
|
||||
targetVersion, _ := strconv.ParseUint(versionStr, 10, 32)
|
||||
return ctx.version >= uint32(targetVersion)
|
||||
}
|
||||
if strings.Contains(condition, "<=") {
|
||||
versionStr := condition[strings.Index(condition, "<=")+2:]
|
||||
targetVersion, _ := strconv.ParseUint(versionStr, 10, 32)
|
||||
return ctx.version <= uint32(targetVersion)
|
||||
}
|
||||
if strings.Contains(condition, ">") {
|
||||
versionStr := condition[strings.Index(condition, ">")+1:]
|
||||
targetVersion, _ := strconv.ParseUint(versionStr, 10, 32)
|
||||
return ctx.version > uint32(targetVersion)
|
||||
}
|
||||
if strings.Contains(condition, "<") {
|
||||
versionStr := condition[strings.Index(condition, "<")+1:]
|
||||
targetVersion, _ := strconv.ParseUint(versionStr, 10, 32)
|
||||
return ctx.version < uint32(targetVersion)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) evaluateStringLength(varName, valueStr, op string) bool {
|
||||
resolvedName := ctx.resolveVariableName(varName)
|
||||
str := ctx.getStringVar(resolvedName)
|
||||
targetLen, _ := strconv.Atoi(valueStr)
|
||||
strLen := len(str)
|
||||
|
||||
switch op {
|
||||
case "!>":
|
||||
return strLen > targetLen
|
||||
case "!<":
|
||||
return strLen < targetLen
|
||||
case "!>=":
|
||||
return strLen >= targetLen
|
||||
case "!<=":
|
||||
return strLen <= targetLen
|
||||
case "!=":
|
||||
return strLen != targetLen
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) evaluateComparison(varName, valueStr, op string) bool {
|
||||
resolvedName := ctx.resolveVariableName(varName)
|
||||
varValue := ctx.getVarValue(resolvedName)
|
||||
targetValue, _ := strconv.ParseUint(valueStr, 0, 64)
|
||||
|
||||
switch op {
|
||||
case ">=":
|
||||
return varValue >= targetValue
|
||||
case "<=":
|
||||
return varValue <= targetValue
|
||||
case ">":
|
||||
return varValue > targetValue
|
||||
case "<":
|
||||
return varValue < targetValue
|
||||
case "==":
|
||||
return varValue == targetValue
|
||||
case "!=":
|
||||
return varValue != targetValue
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) hasVar(name string) bool {
|
||||
if val, exists := ctx.vars[name]; exists {
|
||||
switch v := val.(type) {
|
||||
case uint8, uint16, uint32, uint64:
|
||||
return ctx.getVarValue(name) != 0
|
||||
case string:
|
||||
return v != ""
|
||||
case common.EQ2String8:
|
||||
return v.Data != ""
|
||||
case common.EQ2String16:
|
||||
return v.Data != ""
|
||||
case common.EQ2String32:
|
||||
return v.Data != ""
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) getVarValue(name string) uint64 {
|
||||
if val, exists := ctx.vars[name]; exists {
|
||||
switch v := val.(type) {
|
||||
case uint8:
|
||||
return uint64(v)
|
||||
case uint16:
|
||||
return uint64(v)
|
||||
case uint32:
|
||||
return uint64(v)
|
||||
case uint64:
|
||||
return v
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) getStringVar(name string) string {
|
||||
if val, exists := ctx.vars[name]; exists {
|
||||
switch v := val.(type) {
|
||||
case string:
|
||||
return v
|
||||
case common.EQ2String8:
|
||||
return v.Data
|
||||
case common.EQ2String16:
|
||||
return v.Data
|
||||
case common.EQ2String32:
|
||||
return v.Data
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) getFlagValue(flagName string) uint64 {
|
||||
flagMap := map[string]uint64{
|
||||
"loot": 0x01,
|
||||
"has_equipment": 0x02,
|
||||
"no_colors": 0x04,
|
||||
}
|
||||
if val, exists := flagMap[flagName]; exists {
|
||||
return val
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) getArraySize(condition string) int {
|
||||
if strings.HasPrefix(condition, "var:") {
|
||||
varName := condition[4:]
|
||||
return int(ctx.getVarValue(varName))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) resolveVariableName(name string) string {
|
||||
// Handle %i substitution for array contexts
|
||||
if strings.Contains(name, "%i") && len(ctx.arrayStack) > 0 {
|
||||
currentIndex := ctx.arrayStack[len(ctx.arrayStack)-1]
|
||||
return strings.ReplaceAll(name, "%i", strconv.Itoa(currentIndex))
|
||||
}
|
||||
return name
|
||||
}
|
||||
|
||||
func (ctx *ParseContext) setVarWithArrayIndex(name string, value any) {
|
||||
// Always set the base variable name
|
||||
ctx.vars[name] = value
|
||||
|
||||
// If we're in an array context, also set the indexed variable
|
||||
if len(ctx.arrayStack) > 0 {
|
||||
currentIndex := ctx.arrayStack[len(ctx.arrayStack)-1]
|
||||
indexedName := name + "_" + strconv.Itoa(currentIndex)
|
||||
ctx.vars[indexedName] = value
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// FieldTag represents parsed tag parameters
|
||||
type FieldTag struct {
|
||||
Type string
|
||||
Length int
|
||||
DynamicLen string
|
||||
Condition *FieldCondition
|
||||
MaxSize int
|
||||
SkipOversized bool
|
||||
OversizedValue int
|
||||
OversizedByte byte
|
||||
Type2 string
|
||||
Type2Criteria string
|
||||
ArraySizeVar string
|
||||
IfVariableSet string
|
||||
IfVariableNotSet string
|
||||
IfFlag string
|
||||
IfFlagNotSet string
|
||||
IfEquals string
|
||||
IfNotEquals string
|
||||
Optional bool
|
||||
}
|
||||
|
||||
// FieldCondition represents XML conditional logic
|
||||
type FieldCondition struct {
|
||||
Type string // "if_set", "if_not_set", "if_flag", etc.
|
||||
Variable string
|
||||
Value string
|
||||
Operator string
|
||||
}
|
||||
|
||||
// parseFieldTag extracts all tag parameters
|
||||
func (p *Parser) parseFieldTag(tag string) *FieldTag {
|
||||
parts := strings.Split(tag, ",")
|
||||
fieldTag := &FieldTag{
|
||||
Type: parts[0],
|
||||
Length: 1,
|
||||
MaxSize: -1,
|
||||
OversizedValue: -1,
|
||||
OversizedByte: 127,
|
||||
}
|
||||
|
||||
for _, part := range parts[1:] {
|
||||
p.parseTagParameter(fieldTag, part)
|
||||
}
|
||||
|
||||
return fieldTag
|
||||
}
|
||||
|
||||
// parseTagParameter processes individual tag parameters
|
||||
func (p *Parser) parseTagParameter(fieldTag *FieldTag, part string) {
|
||||
switch {
|
||||
case strings.HasPrefix(part, "len="):
|
||||
lenVal := part[4:]
|
||||
if l, err := strconv.Atoi(lenVal); err == nil {
|
||||
fieldTag.Length = l
|
||||
} else {
|
||||
fieldTag.DynamicLen = lenVal
|
||||
}
|
||||
case strings.HasPrefix(part, "if="):
|
||||
fieldTag.Condition = p.parseCondition(part[3:])
|
||||
case strings.HasPrefix(part, "maxsize="):
|
||||
if m, err := strconv.Atoi(part[8:]); err == nil {
|
||||
fieldTag.MaxSize = m
|
||||
}
|
||||
case part == "skipoversized":
|
||||
fieldTag.SkipOversized = true
|
||||
case strings.HasPrefix(part, "oversized="):
|
||||
if o, err := strconv.Atoi(part[10:]); err == nil {
|
||||
fieldTag.OversizedValue = o
|
||||
}
|
||||
case strings.HasPrefix(part, "oversizedbyte="):
|
||||
if o, err := strconv.Atoi(part[14:]); err == nil {
|
||||
fieldTag.OversizedByte = byte(o)
|
||||
}
|
||||
case strings.HasPrefix(part, "type2="):
|
||||
fieldTag.Type2 = part[6:]
|
||||
case strings.HasPrefix(part, "type2criteria="):
|
||||
fieldTag.Type2Criteria = part[14:]
|
||||
case strings.HasPrefix(part, "arraysize="):
|
||||
fieldTag.ArraySizeVar = part[10:]
|
||||
case strings.HasPrefix(part, "ifvariableset="):
|
||||
fieldTag.IfVariableSet = part[14:]
|
||||
case strings.HasPrefix(part, "ifvariablenotset="):
|
||||
fieldTag.IfVariableNotSet = part[17:]
|
||||
case strings.HasPrefix(part, "ifflag="):
|
||||
fieldTag.IfFlag = part[7:]
|
||||
case strings.HasPrefix(part, "ifflagnotset="):
|
||||
fieldTag.IfFlagNotSet = part[13:]
|
||||
case strings.HasPrefix(part, "ifequals="):
|
||||
fieldTag.IfEquals = part[9:]
|
||||
case strings.HasPrefix(part, "ifnotequals="):
|
||||
fieldTag.IfNotEquals = part[12:]
|
||||
case part == "optional":
|
||||
fieldTag.Optional = true
|
||||
}
|
||||
}
|
||||
|
||||
// parseCondition creates FieldCondition from condition string with enhanced operator support
|
||||
func (p *Parser) parseCondition(condition string) *FieldCondition {
|
||||
// String length operators must be checked first due to overlapping patterns
|
||||
stringLengthOps := []string{"!>=", "!<=", "!>", "!<", "!="}
|
||||
|
||||
for _, op := range stringLengthOps {
|
||||
if idx := strings.Index(condition, op); idx > 0 {
|
||||
return &FieldCondition{
|
||||
Variable: strings.TrimSpace(condition[:idx]),
|
||||
Value: strings.TrimSpace(condition[idx+len(op):]),
|
||||
Operator: op,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Standard comparison operators
|
||||
operators := []string{">=", "<=", ">", "<", "==", "&", "|"}
|
||||
|
||||
for _, op := range operators {
|
||||
if idx := strings.Index(condition, op); idx > 0 {
|
||||
return &FieldCondition{
|
||||
Variable: strings.TrimSpace(condition[:idx]),
|
||||
Value: strings.TrimSpace(condition[idx+len(op):]),
|
||||
Operator: op,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return &FieldCondition{
|
||||
Type: "simple",
|
||||
Variable: condition,
|
||||
}
|
||||
}
|
@ -1,375 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// getDynamicLength gets length from another field with stack support and array index resolution
|
||||
func (p *Parser) getDynamicLength(fieldName string) int {
|
||||
// Handle %i patterns by replacing with current array index
|
||||
if strings.Contains(fieldName, "%i") {
|
||||
currentIndex := p.GetCurrentArrayIndex()
|
||||
if currentIndex >= 0 {
|
||||
fieldName = strings.ReplaceAll(fieldName, "%i", strconv.Itoa(currentIndex))
|
||||
}
|
||||
}
|
||||
|
||||
// Check field cache first
|
||||
if cachedValue, exists := p.fieldCache[fieldName]; exists {
|
||||
return p.valueToInt(cachedValue)
|
||||
}
|
||||
|
||||
// Handle array index patterns like "header_info_mod_need_0"
|
||||
if strings.Contains(fieldName, "_") {
|
||||
if value, exists := p.resolveArrayIndexVariableForLength(fieldName); exists {
|
||||
return p.valueToInt(value)
|
||||
}
|
||||
}
|
||||
|
||||
// Check current struct
|
||||
if p.currentStruct.IsValid() {
|
||||
if field := p.currentStruct.FieldByName(fieldName); field.IsValid() {
|
||||
return p.valueToInt(field.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
// Check struct stack for nested resolution
|
||||
for i := len(p.structStack) - 1; i >= 0; i-- {
|
||||
if field := p.structStack[i].FieldByName(fieldName); field.IsValid() {
|
||||
return p.valueToInt(field.Interface())
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
// resolveArrayIndexVariableForLength handles array index variable resolution for length calculations
|
||||
func (p *Parser) resolveArrayIndexVariableForLength(variable string) (any, bool) {
|
||||
parts := strings.Split(variable, "_")
|
||||
if len(parts) < 2 {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Try to extract index from last part
|
||||
lastPart := parts[len(parts)-1]
|
||||
if index, err := strconv.Atoi(lastPart); err == nil {
|
||||
// Reconstruct base variable name without index
|
||||
baseVar := strings.Join(parts[:len(parts)-1], "_")
|
||||
|
||||
// Look for array/slice field with this base name
|
||||
if cachedValue, exists := p.fieldCache[baseVar]; exists {
|
||||
return p.getArrayElementSafe(cachedValue, index)
|
||||
}
|
||||
|
||||
// Check current struct for array field
|
||||
if p.currentStruct.IsValid() {
|
||||
if field := p.currentStruct.FieldByName(baseVar); field.IsValid() {
|
||||
return p.getArrayElementSafe(field.Interface(), index)
|
||||
}
|
||||
}
|
||||
|
||||
// Check struct stack
|
||||
for i := len(p.structStack) - 1; i >= 0; i-- {
|
||||
if field := p.structStack[i].FieldByName(baseVar); field.IsValid() {
|
||||
return p.getArrayElementSafe(field.Interface(), index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// getArrayElementSafe safely extracts element from array/slice with bounds checking
|
||||
func (p *Parser) getArrayElementSafe(value any, index int) (any, bool) {
|
||||
val := reflect.ValueOf(value)
|
||||
|
||||
switch val.Kind() {
|
||||
case reflect.Slice, reflect.Array:
|
||||
if index >= 0 && index < val.Len() {
|
||||
return val.Index(index).Interface(), true
|
||||
}
|
||||
}
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// convertValue converts string to appropriate type for comparison with enhanced string support
|
||||
func (p *Parser) convertValue(valueStr string, reference any) (any, error) {
|
||||
switch reference.(type) {
|
||||
case uint8, int8:
|
||||
if val, err := strconv.ParseInt(valueStr, 0, 8); err == nil {
|
||||
return uint8(val), nil
|
||||
}
|
||||
case uint16, int16:
|
||||
if val, err := strconv.ParseInt(valueStr, 0, 16); err == nil {
|
||||
return uint16(val), nil
|
||||
}
|
||||
case uint32, int32:
|
||||
if val, err := strconv.ParseInt(valueStr, 0, 32); err == nil {
|
||||
return uint32(val), nil
|
||||
}
|
||||
case uint64, int64:
|
||||
if val, err := strconv.ParseInt(valueStr, 0, 64); err == nil {
|
||||
return uint64(val), nil
|
||||
}
|
||||
case float32:
|
||||
if val, err := strconv.ParseFloat(valueStr, 32); err == nil {
|
||||
return float32(val), nil
|
||||
}
|
||||
case float64:
|
||||
if val, err := strconv.ParseFloat(valueStr, 64); err == nil {
|
||||
return val, nil
|
||||
}
|
||||
case string:
|
||||
return valueStr, nil
|
||||
}
|
||||
|
||||
// Handle struct types with Data field (EQ2String types)
|
||||
if reflect.TypeOf(reference).Kind() == reflect.Struct {
|
||||
refVal := reflect.ValueOf(reference)
|
||||
if dataField := refVal.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String {
|
||||
return valueStr, nil
|
||||
}
|
||||
}
|
||||
|
||||
if val, err := strconv.ParseInt(valueStr, 0, 32); err == nil {
|
||||
return int(val), nil
|
||||
}
|
||||
|
||||
return valueStr, nil
|
||||
}
|
||||
|
||||
// compareValues performs comparison between two values with enhanced string support
|
||||
func (p *Parser) compareValues(a, b any, op string) bool {
|
||||
// Handle string comparisons first
|
||||
if p.isStringValue(a) && p.isStringValue(b) {
|
||||
aStr := p.extractStringValue(a)
|
||||
bStr := p.extractStringValue(b)
|
||||
return p.compareStrings(aStr, bStr, op)
|
||||
}
|
||||
|
||||
// Fall back to numeric comparison
|
||||
aVal := p.valueToInt64(a)
|
||||
bVal := p.valueToInt64(b)
|
||||
|
||||
switch op {
|
||||
case "==":
|
||||
return aVal == bVal
|
||||
case "!=":
|
||||
return aVal != bVal
|
||||
case ">":
|
||||
return aVal > bVal
|
||||
case ">=":
|
||||
return aVal >= bVal
|
||||
case "<":
|
||||
return aVal < bVal
|
||||
case "<=":
|
||||
return aVal <= bVal
|
||||
case "&":
|
||||
return (aVal & bVal) != 0
|
||||
case "|":
|
||||
return (aVal | bVal) != 0
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// isStringValue checks if a value is or contains a string
|
||||
func (p *Parser) isStringValue(value any) bool {
|
||||
switch value.(type) {
|
||||
case string:
|
||||
return true
|
||||
default:
|
||||
if reflect.TypeOf(value).Kind() == reflect.Struct {
|
||||
val := reflect.ValueOf(value)
|
||||
if dataField := val.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// extractStringValue extracts string from value or struct Data field
|
||||
func (p *Parser) extractStringValue(value any) string {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
return v
|
||||
default:
|
||||
if reflect.TypeOf(value).Kind() == reflect.Struct {
|
||||
val := reflect.ValueOf(value)
|
||||
if dataField := val.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String {
|
||||
return dataField.String()
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// compareStrings performs string comparison operations
|
||||
func (p *Parser) compareStrings(a, b, op string) bool {
|
||||
switch op {
|
||||
case "==":
|
||||
return a == b
|
||||
case "!=":
|
||||
return a != b
|
||||
case ">":
|
||||
return a > b
|
||||
case ">=":
|
||||
return a >= b
|
||||
case "<":
|
||||
return a < b
|
||||
case "<=":
|
||||
return a <= b
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// valueToInt converts various types to int with enhanced type support
|
||||
func (p *Parser) valueToInt(v any) int {
|
||||
switch val := v.(type) {
|
||||
case uint8:
|
||||
return int(val)
|
||||
case int8:
|
||||
return int(val)
|
||||
case uint16:
|
||||
return int(val)
|
||||
case int16:
|
||||
return int(val)
|
||||
case uint32:
|
||||
return int(val)
|
||||
case int32:
|
||||
return int(val)
|
||||
case uint64:
|
||||
return int(val)
|
||||
case int64:
|
||||
return int(val)
|
||||
case int:
|
||||
return val
|
||||
case bool:
|
||||
if val {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
default:
|
||||
// Handle struct types that might have numeric fields
|
||||
if reflect.TypeOf(v).Kind() == reflect.Struct {
|
||||
refVal := reflect.ValueOf(v)
|
||||
// Try common numeric field names
|
||||
for _, fieldName := range []string{"Value", "Size", "Length", "Count"} {
|
||||
if field := refVal.FieldByName(fieldName); field.IsValid() {
|
||||
return p.valueToInt(field.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// valueToInt64 converts various types to int64 for comparison with enhanced support
|
||||
func (p *Parser) valueToInt64(v any) int64 {
|
||||
switch val := v.(type) {
|
||||
case uint8:
|
||||
return int64(val)
|
||||
case int8:
|
||||
return int64(val)
|
||||
case uint16:
|
||||
return int64(val)
|
||||
case int16:
|
||||
return int64(val)
|
||||
case uint32:
|
||||
return int64(val)
|
||||
case int32:
|
||||
return int64(val)
|
||||
case uint64:
|
||||
return int64(val)
|
||||
case int64:
|
||||
return val
|
||||
case int:
|
||||
return int64(val)
|
||||
case float32:
|
||||
return int64(val)
|
||||
case float64:
|
||||
return int64(val)
|
||||
case bool:
|
||||
if val {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
default:
|
||||
// Handle struct types that might have numeric fields
|
||||
if reflect.TypeOf(v).Kind() == reflect.Struct {
|
||||
refVal := reflect.ValueOf(v)
|
||||
// Try common numeric field names
|
||||
for _, fieldName := range []string{"Value", "Size", "Length", "Count"} {
|
||||
if field := refVal.FieldByName(fieldName); field.IsValid() {
|
||||
return p.valueToInt64(field.Interface())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// isTruthy checks if a value is truthy with enhanced type support
|
||||
func (p *Parser) isTruthy(v any) bool {
|
||||
switch val := v.(type) {
|
||||
case bool:
|
||||
return val
|
||||
case uint8, int8, uint16, int16, uint32, int32, uint64, int64, int:
|
||||
return p.valueToInt64(val) != 0
|
||||
case string:
|
||||
return val != ""
|
||||
default:
|
||||
// Handle struct types
|
||||
if reflect.TypeOf(v).Kind() == reflect.Struct {
|
||||
refVal := reflect.ValueOf(v)
|
||||
// Check for Data field (string types)
|
||||
if dataField := refVal.FieldByName("Data"); dataField.IsValid() && dataField.Kind() == reflect.String {
|
||||
return dataField.String() != ""
|
||||
}
|
||||
// Check for numeric fields
|
||||
for _, fieldName := range []string{"Value", "Size", "Length", "Count"} {
|
||||
if field := refVal.FieldByName(fieldName); field.IsValid() {
|
||||
return p.valueToInt64(field.Interface()) != 0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// handleOversizedField handles fields that exceed their oversized value
|
||||
func (p *Parser) handleOversizedField(field reflect.Value, oversizedByte byte, length int) error {
|
||||
if field.Kind() == reflect.Slice {
|
||||
slice := reflect.MakeSlice(field.Type(), 1, 1)
|
||||
if slice.Len() > 0 {
|
||||
elem := slice.Index(0)
|
||||
if elem.CanSet() {
|
||||
switch elem.Kind() {
|
||||
case reflect.Uint8:
|
||||
elem.SetUint(uint64(oversizedByte))
|
||||
case reflect.Int8:
|
||||
elem.SetInt(int64(int8(oversizedByte)))
|
||||
default:
|
||||
elem.SetUint(uint64(oversizedByte))
|
||||
}
|
||||
}
|
||||
}
|
||||
field.Set(slice)
|
||||
} else {
|
||||
switch field.Kind() {
|
||||
case reflect.Uint8:
|
||||
field.SetUint(uint64(oversizedByte))
|
||||
case reflect.Int8:
|
||||
field.SetInt(int64(int8(oversizedByte)))
|
||||
default:
|
||||
field.SetUint(uint64(oversizedByte))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
358
internal/packets/parser/lexer.go
Normal file
358
internal/packets/parser/lexer.go
Normal file
@ -0,0 +1,358 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
// Object pools for heavy reuse
|
||||
var tokenPool = sync.Pool{
|
||||
New: func() any {
|
||||
return &Token{
|
||||
Attributes: make(map[string]string, 8),
|
||||
TagStart: -1,
|
||||
TagEnd: -1,
|
||||
TextStart: -1,
|
||||
TextEnd: -1,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// More efficient lexer using byte operations and minimal allocations
|
||||
type Lexer struct {
|
||||
input []byte // Use byte slice for faster operations
|
||||
pos int
|
||||
line int
|
||||
col int
|
||||
}
|
||||
|
||||
// Creates a new lexer
|
||||
func NewLexer(input string) *Lexer {
|
||||
return &Lexer{
|
||||
input: []byte(input),
|
||||
line: 1,
|
||||
col: 1,
|
||||
}
|
||||
}
|
||||
|
||||
// Returns next byte without advancing
|
||||
func (l *Lexer) peek() byte {
|
||||
if l.pos >= len(l.input) {
|
||||
return 0
|
||||
}
|
||||
return l.input[l.pos]
|
||||
}
|
||||
|
||||
// Advances and returns next byte
|
||||
func (l *Lexer) next() byte {
|
||||
if l.pos >= len(l.input) {
|
||||
return 0
|
||||
}
|
||||
ch := l.input[l.pos]
|
||||
l.pos++
|
||||
if ch == '\n' {
|
||||
l.line++
|
||||
l.col = 1
|
||||
} else {
|
||||
l.col++
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
// Checks if a tag should be treated as self-closing (using byte comparison)
|
||||
func (l *Lexer) isSelfClosingTag(start, end int) bool {
|
||||
length := end - start
|
||||
if length < 2 || length > 6 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Fast byte-based comparison
|
||||
switch length {
|
||||
case 2:
|
||||
return (l.input[start] == 'i' && l.input[start+1] == '8') ||
|
||||
(l.input[start] == 'f' && l.input[start+1] == '2')
|
||||
case 3:
|
||||
return (l.input[start] == 'i' && l.input[start+1] == '1' && l.input[start+2] == '6') ||
|
||||
(l.input[start] == 'i' && l.input[start+1] == '3' && l.input[start+2] == '2') ||
|
||||
(l.input[start] == 'i' && l.input[start+1] == '6' && l.input[start+2] == '4') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 'i' && l.input[start+2] == '8') ||
|
||||
(l.input[start] == 'f' && l.input[start+1] == '3' && l.input[start+2] == '2') ||
|
||||
(l.input[start] == 'f' && l.input[start+1] == '6' && l.input[start+2] == '4')
|
||||
case 4:
|
||||
return (l.input[start] == 's' && l.input[start+1] == 'i' &&
|
||||
l.input[start+2] == '1' && l.input[start+3] == '6') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 'i' &&
|
||||
l.input[start+2] == '3' && l.input[start+3] == '2') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 'i' &&
|
||||
l.input[start+2] == '6' && l.input[start+3] == '4') ||
|
||||
(l.input[start] == 'c' && l.input[start+1] == 'h' &&
|
||||
l.input[start+2] == 'a' && l.input[start+3] == 'r') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 't' &&
|
||||
l.input[start+2] == 'r' && l.input[start+3] == '8')
|
||||
case 5:
|
||||
return (l.input[start] == 'c' && l.input[start+1] == 'o' &&
|
||||
l.input[start+2] == 'l' && l.input[start+3] == 'o' &&
|
||||
l.input[start+4] == 'r') ||
|
||||
(l.input[start] == 'e' && l.input[start+1] == 'q' &&
|
||||
l.input[start+2] == 'u' && l.input[start+3] == 'i' &&
|
||||
l.input[start+4] == 'p') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 't' &&
|
||||
l.input[start+2] == 'r' && l.input[start+3] == '1' &&
|
||||
l.input[start+4] == '6') ||
|
||||
(l.input[start] == 's' && l.input[start+1] == 't' &&
|
||||
l.input[start+2] == 'r' && l.input[start+3] == '3' &&
|
||||
l.input[start+4] == '2')
|
||||
case 6:
|
||||
return (l.input[start] == 'd' && l.input[start+1] == 'o' &&
|
||||
l.input[start+2] == 'u' && l.input[start+3] == 'b' &&
|
||||
l.input[start+4] == 'l' && l.input[start+5] == 'e')
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Skips whitespace using byte operations
|
||||
func (l *Lexer) skipWhitespace() {
|
||||
for l.pos < len(l.input) {
|
||||
ch := l.input[l.pos]
|
||||
if ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' {
|
||||
if ch == '\n' {
|
||||
l.line++
|
||||
l.col = 1
|
||||
} else {
|
||||
l.col++
|
||||
}
|
||||
l.pos++
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Optimized attribute parsing with minimal allocations - FIXED BUG
|
||||
func (l *Lexer) parseAttributes(attrs map[string]string) error {
|
||||
// Clear existing attributes without deallocating
|
||||
for k := range attrs {
|
||||
delete(attrs, k)
|
||||
}
|
||||
|
||||
for {
|
||||
l.skipWhitespace()
|
||||
if l.pos >= len(l.input) || l.peek() == '>' ||
|
||||
(l.peek() == '/' && l.pos+1 < len(l.input) && l.input[l.pos+1] == '>') {
|
||||
break
|
||||
}
|
||||
|
||||
// Read attribute name using byte operations
|
||||
nameStart := l.pos
|
||||
for l.pos < len(l.input) {
|
||||
ch := l.input[l.pos]
|
||||
if ch == '=' || ch == ' ' || ch == '\t' || ch == '\n' || ch == '>' {
|
||||
break
|
||||
}
|
||||
l.pos++
|
||||
if ch != '\n' {
|
||||
l.col++
|
||||
}
|
||||
}
|
||||
|
||||
nameEnd := l.pos // FIXED: Store end of name here
|
||||
|
||||
if nameStart == nameEnd {
|
||||
break
|
||||
}
|
||||
|
||||
l.skipWhitespace()
|
||||
if l.peek() != '=' {
|
||||
return fmt.Errorf("expected '=' after attribute name")
|
||||
}
|
||||
l.next() // skip '='
|
||||
l.skipWhitespace()
|
||||
|
||||
// Read attribute value
|
||||
quote := l.peek()
|
||||
if quote != '"' && quote != '\'' {
|
||||
return fmt.Errorf("attribute value must be quoted")
|
||||
}
|
||||
l.next() // skip opening quote
|
||||
|
||||
valueStart := l.pos
|
||||
for l.pos < len(l.input) && l.input[l.pos] != quote {
|
||||
if l.input[l.pos] == '\n' {
|
||||
l.line++
|
||||
l.col = 1
|
||||
} else {
|
||||
l.col++
|
||||
}
|
||||
l.pos++
|
||||
}
|
||||
|
||||
if l.pos >= len(l.input) {
|
||||
return fmt.Errorf("unclosed attribute value")
|
||||
}
|
||||
|
||||
// FIXED: Correct name and value extraction
|
||||
name := string(l.input[nameStart:nameEnd])
|
||||
value := string(l.input[valueStart:l.pos])
|
||||
attrs[name] = value
|
||||
|
||||
l.next() // skip closing quote
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Optimized token generation with pooling
|
||||
func (l *Lexer) NextToken() *Token {
|
||||
token := tokenPool.Get().(*Token)
|
||||
token.Type = TokenError
|
||||
token.TagStart = -1
|
||||
token.TagEnd = -1
|
||||
token.TextStart = -1
|
||||
token.TextEnd = -1
|
||||
token.Line = l.line
|
||||
token.Col = l.col
|
||||
|
||||
l.skipWhitespace()
|
||||
if l.pos >= len(l.input) {
|
||||
token.Type = TokenEOF
|
||||
return token
|
||||
}
|
||||
|
||||
if l.peek() == '<' {
|
||||
l.next() // skip '<'
|
||||
|
||||
// Check for comment using byte comparison
|
||||
if l.pos+2 < len(l.input) &&
|
||||
l.input[l.pos] == '!' && l.input[l.pos+1] == '-' && l.input[l.pos+2] == '-' {
|
||||
l.pos += 3
|
||||
start := l.pos
|
||||
// Find end of comment efficiently
|
||||
for l.pos+2 < len(l.input) {
|
||||
if l.input[l.pos] == '-' && l.input[l.pos+1] == '-' && l.input[l.pos+2] == '>' {
|
||||
token.Type = TokenComment
|
||||
token.TextStart = start
|
||||
token.TextEnd = l.pos
|
||||
l.pos += 3
|
||||
return token
|
||||
}
|
||||
if l.input[l.pos] == '\n' {
|
||||
l.line++
|
||||
l.col = 1
|
||||
} else {
|
||||
l.col++
|
||||
}
|
||||
l.pos++
|
||||
}
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
|
||||
// Check for closing tag
|
||||
if l.peek() == '/' {
|
||||
l.next() // skip '/'
|
||||
start := l.pos
|
||||
for l.pos < len(l.input) && l.input[l.pos] != '>' {
|
||||
l.pos++
|
||||
l.col++
|
||||
}
|
||||
if l.pos >= len(l.input) {
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
token.Type = TokenCloseTag
|
||||
token.TagStart = start
|
||||
token.TagEnd = l.pos
|
||||
l.next() // skip '>'
|
||||
return token
|
||||
}
|
||||
|
||||
// Opening or self-closing tag
|
||||
start := l.pos
|
||||
for l.pos < len(l.input) {
|
||||
ch := l.input[l.pos]
|
||||
if ch == '>' || ch == '/' || ch == ' ' || ch == '\t' || ch == '\n' {
|
||||
break
|
||||
}
|
||||
l.pos++
|
||||
l.col++
|
||||
}
|
||||
|
||||
if start == l.pos {
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
|
||||
token.TagStart = start
|
||||
token.TagEnd = l.pos
|
||||
|
||||
if err := l.parseAttributes(token.Attributes); err != nil {
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
|
||||
l.skipWhitespace()
|
||||
if l.pos >= len(l.input) {
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
|
||||
if l.peek() == '/' && l.pos+1 < len(l.input) && l.input[l.pos+1] == '>' {
|
||||
token.Type = TokenSelfCloseTag
|
||||
l.pos += 2
|
||||
} else {
|
||||
// Check if this is a self-closing field type
|
||||
if l.isSelfClosingTag(token.TagStart, token.TagEnd) {
|
||||
token.Type = TokenSelfCloseTag
|
||||
} else {
|
||||
token.Type = TokenOpenTag
|
||||
}
|
||||
if l.peek() == '>' {
|
||||
l.next()
|
||||
} else {
|
||||
token.Type = TokenError
|
||||
return token
|
||||
}
|
||||
}
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
// Text content - find range without copying
|
||||
start := l.pos
|
||||
for l.pos < len(l.input) && l.input[l.pos] != '<' {
|
||||
if l.input[l.pos] == '\n' {
|
||||
l.line++
|
||||
l.col = 1
|
||||
} else {
|
||||
l.col++
|
||||
}
|
||||
l.pos++
|
||||
}
|
||||
|
||||
// Trim whitespace from range
|
||||
for start < l.pos && unicode.IsSpace(rune(l.input[start])) {
|
||||
start++
|
||||
}
|
||||
end := l.pos
|
||||
for end > start && unicode.IsSpace(rune(l.input[end-1])) {
|
||||
end--
|
||||
}
|
||||
|
||||
if start < end {
|
||||
token.Type = TokenText
|
||||
token.TextStart = start
|
||||
token.TextEnd = end
|
||||
return token
|
||||
}
|
||||
|
||||
// Skip empty text, get next token
|
||||
return l.NextToken()
|
||||
}
|
||||
|
||||
// Returns token to pool
|
||||
func (l *Lexer) ReleaseToken(token *Token) {
|
||||
if token != nil {
|
||||
tokenPool.Put(token)
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
124
internal/packets/parser/structs.go
Normal file
124
internal/packets/parser/structs.go
Normal file
@ -0,0 +1,124 @@
|
||||
package parser
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// PacketDef defines a complete packet structure with versioned field ordering
|
||||
type PacketDef struct {
|
||||
Fields map[string]FieldDesc // Field definitions by name
|
||||
Orders map[uint32][]string // Field order by version number
|
||||
}
|
||||
|
||||
// Creates packet definition with estimated capacity
|
||||
func NewPacketDef(estimatedFields int) *PacketDef {
|
||||
return &PacketDef{
|
||||
Fields: make(map[string]FieldDesc, estimatedFields),
|
||||
Orders: make(map[uint32][]string, 4),
|
||||
}
|
||||
}
|
||||
|
||||
func (def *PacketDef) Parse(data []byte, version uint32, flags uint64) (map[string]any, error) {
|
||||
ctx := NewContext(data, version, flags)
|
||||
return def.parseStruct(ctx)
|
||||
}
|
||||
|
||||
func (def *PacketDef) parseStruct(ctx *ParseContext) (map[string]any, error) {
|
||||
result := make(map[string]any)
|
||||
order := def.getVersionOrder(ctx.version)
|
||||
|
||||
for _, fieldName := range order {
|
||||
field := def.Fields[fieldName]
|
||||
|
||||
if !ctx.checkCondition(field.Condition) {
|
||||
continue
|
||||
}
|
||||
|
||||
fieldType := field.Type
|
||||
if field.Type2 != 0 && ctx.checkCondition(field.Type2Cond) {
|
||||
fieldType = field.Type2
|
||||
}
|
||||
|
||||
value := def.parseField(ctx, field, fieldType, fieldName)
|
||||
result[fieldName] = value
|
||||
ctx.setVarWithArrayIndex(fieldName, value)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (def *PacketDef) parseField(ctx *ParseContext, field FieldDesc, fieldType common.EQ2DataType, fieldName string) any {
|
||||
switch fieldType {
|
||||
case common.TypeInt8, common.TypeSInt8:
|
||||
if field.Oversized > 0 {
|
||||
return ctx.readOversizedUint8(field.Oversized)
|
||||
}
|
||||
return ctx.readUint8()
|
||||
case common.TypeInt16, common.TypeSInt16:
|
||||
if field.Oversized > 0 {
|
||||
return ctx.readOversizedUint16(field.Oversized)
|
||||
}
|
||||
return ctx.readUint16()
|
||||
case common.TypeInt32, common.TypeSInt32:
|
||||
if field.Oversized > 0 {
|
||||
return ctx.readOversizedUint32(field.Oversized)
|
||||
}
|
||||
return ctx.readUint32()
|
||||
case common.TypeInt64, common.TypeSInt64:
|
||||
return ctx.readUint64()
|
||||
case common.TypeString8:
|
||||
return ctx.readEQ2String8()
|
||||
case common.TypeString16:
|
||||
return ctx.readEQ2String16()
|
||||
case common.TypeString32:
|
||||
return ctx.readEQ2String32()
|
||||
case common.TypeChar:
|
||||
return ctx.readBytes(field.Length)
|
||||
case common.TypeFloat:
|
||||
return ctx.readFloat32()
|
||||
case common.TypeDouble:
|
||||
return ctx.readFloat64()
|
||||
case common.TypeColor:
|
||||
return ctx.readEQ2Color()
|
||||
case common.TypeEquipment:
|
||||
return ctx.readEQ2Equipment()
|
||||
case common.TypeArray:
|
||||
size := ctx.getArraySize(field.Condition)
|
||||
if field.MaxArraySize > 0 && size > field.MaxArraySize {
|
||||
size = field.MaxArraySize
|
||||
}
|
||||
result := make([]map[string]any, size)
|
||||
for i := 0; i < size; i++ {
|
||||
ctx.pushArrayIndex(i)
|
||||
item, _ := field.SubDef.parseStruct(ctx)
|
||||
result[i] = item
|
||||
ctx.popArrayIndex()
|
||||
}
|
||||
return result
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (def *PacketDef) getVersionOrder(version uint32) []string {
|
||||
var bestVersion uint32
|
||||
for v := range def.Orders {
|
||||
if v <= version && v > bestVersion {
|
||||
bestVersion = v
|
||||
}
|
||||
}
|
||||
return def.Orders[bestVersion]
|
||||
}
|
||||
|
||||
// FieldDesc describes a single packet field
|
||||
type FieldDesc struct {
|
||||
Type common.EQ2DataType // Primary data type
|
||||
Condition string // Conditional parsing expression
|
||||
Length int // Array length or size for fixed-size fields
|
||||
SubDef *PacketDef // Nested packet definition for arrays
|
||||
Type2 common.EQ2DataType // Alternative data type for conditional parsing
|
||||
Type2Cond string // Condition for using Type2
|
||||
Oversized int // Threshold for oversized field handling
|
||||
DefaultValue int8 // Default value for initialization
|
||||
MaxArraySize int // Maximum allowed array size
|
||||
Optional bool // Whether this field is optional
|
||||
AddToStruct bool // Whether to include in packet structure
|
||||
AddType common.EQ2DataType // Type to use when adding to packet
|
||||
}
|
42
internal/packets/parser/tokens.go
Normal file
42
internal/packets/parser/tokens.go
Normal file
@ -0,0 +1,42 @@
|
||||
package parser
|
||||
|
||||
// Token types for PML parsing
|
||||
type TokenType int
|
||||
|
||||
const (
|
||||
TokenError TokenType = iota
|
||||
TokenOpenTag
|
||||
TokenCloseTag
|
||||
TokenSelfCloseTag
|
||||
TokenText
|
||||
TokenComment
|
||||
TokenEOF
|
||||
)
|
||||
|
||||
// Represents a parsed token with string ranges instead of copies
|
||||
type Token struct {
|
||||
Type TokenType
|
||||
TagStart int // Start index in input for tag name
|
||||
TagEnd int // End index in input for tag name
|
||||
TextStart int // Start index for text content
|
||||
TextEnd int // End index for text content
|
||||
Attributes map[string]string
|
||||
Line int
|
||||
Col int
|
||||
}
|
||||
|
||||
// Gets tag name from input (avoids allocation until needed)
|
||||
func (t *Token) Tag(input string) string {
|
||||
if t.TagStart >= 0 && t.TagEnd > t.TagStart {
|
||||
return input[t.TagStart:t.TagEnd]
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Gets text content from input
|
||||
func (t *Token) Text(input string) string {
|
||||
if t.TextStart >= 0 && t.TextEnd > t.TextStart {
|
||||
return input[t.TextStart:t.TextEnd]
|
||||
}
|
||||
return ""
|
||||
}
|
@ -1,434 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"eq2emu/internal/common"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
func (p *Parser) readInt8(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetUint(uint64(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]uint8, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readInt16(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetUint(uint64(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]uint16, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readInt32(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle interface{} fields
|
||||
if field.Kind() == reflect.Interface {
|
||||
field.Set(reflect.ValueOf(val))
|
||||
} else {
|
||||
field.SetUint(uint64(val))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]uint32, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readInt64(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetUint(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]uint64, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readSInt8(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetInt(int64(int8(val)))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]int8, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = int8(val)
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readSInt16(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetInt(int64(int16(val)))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]int16, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = int16(val)
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readSInt32(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetInt(int64(int32(val)))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]int32, length)
|
||||
for i := range length {
|
||||
val, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = int32(val)
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readSInt64(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetInt(int64(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]int64, length)
|
||||
for i := 0; i < length; i++ {
|
||||
val, err := p.readUint64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = int64(val)
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readChar(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetUint(uint64(val))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]byte, length)
|
||||
err := p.readBytes(slice)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetBytes(slice)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readFloat(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readFloat32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle interface{} fields
|
||||
if field.Kind() == reflect.Interface {
|
||||
field.Set(reflect.ValueOf(val))
|
||||
} else {
|
||||
field.SetFloat(float64(val))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]float32, length)
|
||||
for i := range length {
|
||||
val, err := p.readFloat32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readDouble(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
val, err := p.readFloat64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.SetFloat(val)
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]float64, length)
|
||||
for i := range length {
|
||||
val, err := p.readFloat64()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i] = val
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readString8(field reflect.Value) error {
|
||||
size, err := p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := make([]byte, size)
|
||||
err = p.readBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
str8 := common.EQ2String8{
|
||||
Size: size,
|
||||
Data: string(data),
|
||||
}
|
||||
field.Set(reflect.ValueOf(str8))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readString16(field reflect.Value) error {
|
||||
size, err := p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := make([]byte, size)
|
||||
err = p.readBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
str16 := common.EQ2String16{
|
||||
Size: size,
|
||||
Data: string(data),
|
||||
}
|
||||
field.Set(reflect.ValueOf(str16))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readString32(field reflect.Value) error {
|
||||
size, err := p.readUint32()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
data := make([]byte, size)
|
||||
err = p.readBytes(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
str32 := common.EQ2String32{
|
||||
Size: size,
|
||||
Data: string(data),
|
||||
}
|
||||
field.Set(reflect.ValueOf(str32))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readColor(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
color := common.EQ2Color{}
|
||||
var err error
|
||||
color.Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
color.Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
color.Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
field.Set(reflect.ValueOf(color))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]common.EQ2Color, length)
|
||||
for i := range length {
|
||||
var err error
|
||||
slice[i].Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Parser) readEquipment(field reflect.Value, length int) error {
|
||||
if length == 1 {
|
||||
equipment := common.EQ2EquipmentItem{}
|
||||
var err error
|
||||
equipment.Type, err = p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
equipment.Color.Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
equipment.Color.Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
equipment.Color.Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
equipment.Highlight.Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
equipment.Highlight.Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
equipment.Highlight.Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
field.Set(reflect.ValueOf(equipment))
|
||||
return nil
|
||||
}
|
||||
|
||||
slice := make([]common.EQ2EquipmentItem, length)
|
||||
for i := range length {
|
||||
var err error
|
||||
slice[i].Type, err = p.readUint16()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
slice[i].Color.Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Color.Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Color.Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
slice[i].Highlight.Red, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Highlight.Green, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
slice[i].Highlight.Blue, err = p.readUint8()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
field.Set(reflect.ValueOf(slice))
|
||||
return nil
|
||||
}
|
@ -1,71 +0,0 @@
|
||||
package parser
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// VersionRegistry manages version-specific struct types
|
||||
type VersionRegistry struct {
|
||||
structs map[string]map[string]reflect.Type // [structName][version] = Type
|
||||
}
|
||||
|
||||
// NewVersionRegistry creates a new version registry
|
||||
func NewVersionRegistry() *VersionRegistry {
|
||||
return &VersionRegistry{
|
||||
structs: make(map[string]map[string]reflect.Type),
|
||||
}
|
||||
}
|
||||
|
||||
// RegisterStruct registers a struct type for a specific version
|
||||
func (vr *VersionRegistry) RegisterStruct(name, version string, structType reflect.Type) {
|
||||
if vr.structs[name] == nil {
|
||||
vr.structs[name] = make(map[string]reflect.Type)
|
||||
}
|
||||
vr.structs[name][version] = structType
|
||||
}
|
||||
|
||||
// GetStruct returns the appropriate struct type for a version
|
||||
func (vr *VersionRegistry) GetStruct(name, version string) (reflect.Type, bool) {
|
||||
if versions, exists := vr.structs[name]; exists {
|
||||
if structType, exists := versions[version]; exists {
|
||||
return structType, true
|
||||
}
|
||||
return vr.findNearestVersion(name, version)
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// findNearestVersion finds the closest version <= requested version
|
||||
func (vr *VersionRegistry) findNearestVersion(name, targetVersion string) (reflect.Type, bool) {
|
||||
versions := vr.structs[name]
|
||||
var bestVersion string
|
||||
var bestType reflect.Type
|
||||
|
||||
for version, structType := range versions {
|
||||
if version <= targetVersion && version > bestVersion {
|
||||
bestVersion = version
|
||||
bestType = structType
|
||||
}
|
||||
}
|
||||
|
||||
return bestType, bestVersion != ""
|
||||
}
|
||||
|
||||
// ParseWithVersion parses using version-specific struct
|
||||
func (p *Parser) ParseWithVersion(registry *VersionRegistry, structName, version string) (any, error) {
|
||||
structType, exists := registry.GetStruct(structName, version)
|
||||
if !exists {
|
||||
return nil, fmt.Errorf("no struct found for %s version %s", structName, version)
|
||||
}
|
||||
|
||||
ptr := reflect.New(structType)
|
||||
elem := ptr.Elem()
|
||||
|
||||
err := p.ParseStruct(ptr.Interface())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return elem.Interface(), nil
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// AASpellInfo client version 1193
|
||||
type AASpellInfo struct {
|
||||
ID uint32 `eq2:"int32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Icon2 uint16 `eq2:"int16"`
|
||||
IconType uint16 `eq2:"int16"`
|
||||
Version uint16 `eq2:"int16"`
|
||||
SubVersion uint16 `eq2:"int16"`
|
||||
Type uint8 `eq2:"int8"`
|
||||
ClassSkill uint32 `eq2:"int32"`
|
||||
MasterySkill uint32 `eq2:"int32"`
|
||||
MinClassSkillReq uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SpellTextColor uint32 `eq2:"int32"`
|
||||
Unknown605MJ3 uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
HealthReq uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
HealthUpkeep uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
PowerReq uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
PowerUpkeep uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ReqConcentration uint16 `eq2:"int16"`
|
||||
Unknown uint16 `eq2:"int16"`
|
||||
CastTime uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
Recovery uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
Recast float32 `eq2:"float"`
|
||||
Radius float32 `eq2:"float"`
|
||||
MaxAoeTargets uint16 `eq2:"int16"`
|
||||
FriendlySpell uint8 `eq2:"int8"`
|
||||
NumReagents uint8 `eq2:"int8"`
|
||||
ReagentArray []AASpellReagent `eq2:"array,arraysize=NumReagents"`
|
||||
NumEffects uint8 `eq2:"int8"`
|
||||
EffectArray []AASpellEffect `eq2:"array,arraysize=NumEffects"`
|
||||
DisplaySpellTier uint8 `eq2:"int8"`
|
||||
Unknown1 uint8 `eq2:"int8"`
|
||||
MinimumRange float32 `eq2:"float"`
|
||||
Range float32 `eq2:"float"`
|
||||
Duration1 uint32 `eq2:"int32"`
|
||||
Duration2 uint32 `eq2:"int32"`
|
||||
Unknown9 uint8 `eq2:"int8"`
|
||||
DurationFlag uint8 `eq2:"int8"`
|
||||
Target uint8 `eq2:"int8"`
|
||||
CanEffectRaid uint8 `eq2:"int8"`
|
||||
AffectOnlyGroupMembers uint8 `eq2:"int8"`
|
||||
GroupSpell uint8 `eq2:"int8"`
|
||||
Resistibility float32 `eq2:"float"`
|
||||
Unknown11 []uint8 `eq2:"int8,len=7"`
|
||||
HitBonus float32 `eq2:"float"`
|
||||
Unknown12 uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
Unknown605MJ6 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type AASpellReagent struct {
|
||||
Reagent common.EQ2String8 `eq2:"string8"`
|
||||
Consumed uint8 `eq2:"int8"`
|
||||
QtyRequired uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
type AASpellEffect struct {
|
||||
SubBulletFlag uint8 `eq2:"int8"`
|
||||
Effect common.EQ2String16 `eq2:"string16"`
|
||||
Percentage uint8 `eq2:"int8"`
|
||||
}
|
39
internal/packets/substructs/AASpellInfo.xml
Normal file
39
internal/packets/substructs/AASpellInfo.xml
Normal file
@ -0,0 +1,39 @@
|
||||
<substruct name="AASpellInfo">
|
||||
<version number="1193">
|
||||
<i32 name="id">
|
||||
<i16 name="icon,icon2,icontype,version,sub_version">
|
||||
<i8 name="type">
|
||||
<i32 name="class_skill,mastery_skill">
|
||||
<i16 name="min_class_skill_req" oversized="127">
|
||||
<i32 name="spell_text_color">
|
||||
<i8 name="unknown_605_MJ_3,tier">
|
||||
<i16 name="health_req,health_upkeep,power_req,power_upkeep" oversized="127">
|
||||
<i16 name="req_concentration,unknown">
|
||||
<i16 name="cast_time,recovery" oversized="127">
|
||||
<f32 name="recast,radius">
|
||||
<i16 name="max_aoe_targets">
|
||||
<i8 name="friendly_spell,num_reagents">
|
||||
<array name="reagent_array" count="var:num_reagents">
|
||||
<str8 name="reagent">
|
||||
<i8 name="consumed">
|
||||
<i32 name="qty_required">
|
||||
</array>
|
||||
<i8 name="num_effects">
|
||||
<array name="effect_array" count="var:num_effects">
|
||||
<i8 name="subbulletflag">
|
||||
<str16 name="effect">
|
||||
<i8 name="percentage">
|
||||
</array>
|
||||
<i8 name="display_spell_tier,unknown1">
|
||||
<f32 name="minimum_range,range">
|
||||
<i32 name="duration1,duration2">
|
||||
<i8 name="unknown9,duration_flag,target,can_effect_raid,affect_only_group_members,group_spell">
|
||||
<f32 name="resistibility">
|
||||
<i8 name="unknown11" size="7">
|
||||
<f32 name="hit_bonus">
|
||||
<i8 name="unknown12">
|
||||
<str8 name="name">
|
||||
<str16 name="description">
|
||||
<i8 name="unknown_605_MJ_6">
|
||||
</version>
|
||||
</substruct>
|
@ -1,304 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// BaseItemDescription Version 1
|
||||
type BaseItemDescriptionV1 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
FlagNames common.EQ2String8 `eq2:"string8"`
|
||||
Unknown81 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStat `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillRecommended uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 373
|
||||
type BaseItemDescriptionV373 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
FlagNames common.EQ2String8 `eq2:"string8"`
|
||||
Unknown81 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStat `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillRecommended uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 546
|
||||
type BaseItemDescriptionV546 struct {
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BrokerItemID uint64 `eq2:"int64"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint32 `eq2:"int32"`
|
||||
Unknown81 []uint8 `eq2:"int8,len=15"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatV546 `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringV546 `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 1096
|
||||
type BaseItemDescriptionV1096 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BrokerItemID uint64 `eq2:"int64"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown81096 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatV1096 `eq2:"array,arraysize=StatCount"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringV1096 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
Unknown20 uint16 `eq2:"int16"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 1188
|
||||
type BaseItemDescriptionV1188 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BrokerItemID uint64 `eq2:"int64"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown81188 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatV1188 `eq2:"array,arraysize=StatCount"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringV1188 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
Unknown20 uint16 `eq2:"int16"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 1208
|
||||
type BaseItemDescriptionV1208 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BrokerItemID uint64 `eq2:"int64"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown81208 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatV1208 `eq2:"array,arraysize=StatCount"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringV1208 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
Unknown20 uint16 `eq2:"int16"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseItemDescription Version 63119
|
||||
type BaseItemDescriptionV63119 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BrokerItemID uint64 `eq2:"int64"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown863119 []uint8 `eq2:"int8,len=17"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringV63119 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatV63119 `eq2:"array,arraysize=StatCount"`
|
||||
Unknown20 uint8 `eq2:"int8"`
|
||||
ModCount uint8 `eq2:"int8"`
|
||||
ModArray []BaseItemMod `eq2:"array,arraysize=ModCount"`
|
||||
Unknown21 []uint8 `eq2:"int8,len=4"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// Common nested structs for BaseItemDescription
|
||||
type BaseItemStat struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
Value int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatV546 struct {
|
||||
StatType uint8 `eq2:"int8"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
Value int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatV1096 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
Value any `eq2:"float,type2=sint16,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatV1188 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=stat_type_%i"`
|
||||
Value any `eq2:"float,type2=sint16,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
StatUnknown uint8 `eq2:"int8,ifequals=stat_type_%i"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
StatLevel uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type BaseItemStatV1208 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=stat_type_%i"`
|
||||
Value any `eq2:"float,type2=sint16,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
StatUnknown uint8 `eq2:"int8,ifequals=stat_type_%i"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
StatLevel any `eq2:"int16,type2=int8,type2criteria=stat_name!>2"`
|
||||
}
|
||||
|
||||
type BaseItemStatV63119 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=stat_type_%i"`
|
||||
Value any `eq2:"float,type2=sint32,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
StatLevel any `eq2:"int16,type2=int8,type2criteria=stat_name!>2"`
|
||||
Value2 any `eq2:"float,type2=sint32,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
}
|
||||
|
||||
type BaseItemStatString struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
AdornmentFlag uint8 `eq2:"int8"`
|
||||
AdornmentArray []AdornmentUnknown `eq2:"array,arraysize=AdornmentFlag"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringV546 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringV1096 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringV1188 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringV1208 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringV63119 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type AdornmentUnknown struct {
|
||||
AdornmentUnknown uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type BaseItemClass struct {
|
||||
AdventureClass uint8 `eq2:"int8"`
|
||||
TradeskillClass uint8 `eq2:"int8"`
|
||||
Level uint16 `eq2:"int16"`
|
||||
}
|
||||
|
||||
type BaseItemMod struct {
|
||||
ModString common.EQ2String8 `eq2:"string8"`
|
||||
ModNeed uint8 `eq2:"int8"`
|
||||
ModHave uint8 `eq2:"int8,ifvariableset=header_info_mod_need_0"`
|
||||
ModUnknown []uint8 `eq2:"int8,len=2"`
|
||||
}
|
484
internal/packets/substructs/BaseItemDescription.xml
Normal file
484
internal/packets/substructs/BaseItemDescription.xml
Normal file
@ -0,0 +1,484 @@
|
||||
<substruct name="BaseItemDescription">
|
||||
<version number="1">
|
||||
<i8 name="creator_flag">
|
||||
<str16 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i16 name="icon">
|
||||
<str8 name="flag_names">
|
||||
<i8 name="unknown8_1" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<si16 name="value" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="adornment_flag">
|
||||
<array name="adornment_array" count="var:adornment_flag">
|
||||
<i8 name="adornment_unknown">
|
||||
</array>
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i8 name="condition">
|
||||
<i16 name="weight" oversized="127">
|
||||
<i32 name="skill_req1">
|
||||
<i16 name="skill_min,skill_recommended" oversized="127">
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
</version>
|
||||
|
||||
<version number="373">
|
||||
<i8 name="creator_flag">
|
||||
<str16 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<str8 name="flag_names">
|
||||
<i8 name="unknown8_1" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<si16 name="value" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="adornment_flag">
|
||||
<array name="adornment_array" count="var:adornment_flag">
|
||||
<i8 name="adornment_unknown">
|
||||
</array>
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i8 name="condition">
|
||||
<i16 name="weight" oversized="127">
|
||||
<i32 name="skill_req1,skill_req2">
|
||||
<i16 name="skill_min,skill_recommended" oversized="127">
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
</version>
|
||||
|
||||
<version number="546">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i32 name="flags">
|
||||
<i8 name="unknown8_1" size="15">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i8 name="stat_type">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<si16 name="value" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
</array>
|
||||
<i8 name="condition">
|
||||
<i16 name="weight" oversized="127">
|
||||
<i32 name="skill_req1,skill_req2">
|
||||
<i16 name="skill_min">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="562">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<str16 name="adornment">
|
||||
<i32 name="adornment_id,unknown3">
|
||||
<str16 name="first_desc">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i32 name="flags">
|
||||
<i8 name="unknown8_1" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<si16 name="value" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="adornment_flag">
|
||||
<array name="adornment_array" count="var:adornment_flag">
|
||||
<i8 name="adornment_unknown">
|
||||
</array>
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i8 name="condition">
|
||||
<i32 name="weight">
|
||||
<i32 name="skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="860">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<str16 name="adornment">
|
||||
<i32 name="adornment_id,unknown3">
|
||||
<str16 name="adornment_desc,unknown_desc,first_desc">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i32 name="flags">
|
||||
<i8 name="unknown8_860" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<si16 name="value" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="adornment_flag">
|
||||
<array name="adornment_array" count="var:adornment_flag">
|
||||
<i8 name="adornment_unknown">
|
||||
</array>
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="1096">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_BID_1096" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127">
|
||||
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<str16 name="stat_description">
|
||||
<i8 name="stat_string_unknown">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="1188">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_1188" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||
<i8 name="stat_unknown" if="var:stat_type_%i">
|
||||
<str8 name="stat_name">
|
||||
<i8 name="stat_level">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="1208">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_1208" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si16" type2_if="stat_type!=6" oversized="127">
|
||||
<i8 name="stat_unknown" if="var:stat_type_%i">
|
||||
<str8 name="stat_name">
|
||||
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="58571">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_58570" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="58617">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_58617" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||
<f32 name="value2" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="60174">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_60174" size="17">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||
</array>
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19,unknown20">
|
||||
<i32 name="unknown21">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
|
||||
<version number="63119">
|
||||
<i8 name="creator_flag">
|
||||
<str8 name="creator">
|
||||
<i32 name="unique_id">
|
||||
<i64 name="broker_item_id">
|
||||
<si32 name="item_id,item_crc">
|
||||
<i16 name="icon">
|
||||
<i8 name="tier">
|
||||
<i16 name="flags,flags2">
|
||||
<i8 name="unknown8_63119" size="17">
|
||||
<i8 name="stat_unknown,stat_string_count">
|
||||
<array name="stat_string_array" count="var:stat_string_count">
|
||||
<str8 name="stat_string">
|
||||
<i8 name="stat_string_unknown">
|
||||
<str16 name="stat_description">
|
||||
</array>
|
||||
<i16 name="unknown19">
|
||||
<i8 name="stat_count">
|
||||
<array name="stat_array" count="var:stat_count">
|
||||
<i16 name="stat_type" oversized="127">
|
||||
<si16 name="stat_subtype" oversized="127" if="!var:stat_type_%i">
|
||||
<f32 name="value" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
<str8 name="stat_name">
|
||||
<i16 name="stat_level" type2="i8" type2_if="stat_name!>2">
|
||||
<f32 name="value2" type2="si32" type2_if="stat_type!=6" oversized="127">
|
||||
</array>
|
||||
<i8 name="unknown20,mod_count">
|
||||
<array name="mod_array" count="var:mod_count">
|
||||
<str8 name="mod_string">
|
||||
<i8 name="mod_need">
|
||||
<i8 name="mod_have" if="var:header_info_mod_need_0">
|
||||
<i8 name="mod_unknown" size="2">
|
||||
</array>
|
||||
<i8 name="unknown21" size="4">
|
||||
<i8 name="condition">
|
||||
<i32 name="weight,skill_req1,skill_req2">
|
||||
<i16 name="skill_min" oversized="127">
|
||||
<i8 name="class_count">
|
||||
<array name="class_array" count="var:class_count">
|
||||
<i8 name="adventure_class,tradeskill_class">
|
||||
<i16 name="level">
|
||||
</array>
|
||||
<i8 name="slot_count">
|
||||
<array name="slot_array" count="var:slot_count">
|
||||
<i8 name="slot">
|
||||
</array>
|
||||
<i32 name="footer_type">
|
||||
</version>
|
||||
</substruct>
|
@ -1,26 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// BaseItemDescriptionGeneric Version 373
|
||||
type BaseItemDescriptionGeneric struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
FlagNames common.EQ2String8 `eq2:"string8"`
|
||||
Unknown81 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStat `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SkillRecommended uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// BaseItemDescriptionInspect Version 373
|
||||
type BaseItemDescriptionInspect struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
FlagNames common.EQ2String8 `eq2:"string8"`
|
||||
Unknown81 []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStat `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
Unknown []uint8 `eq2:"int8,len=9"`
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// BaseMerchantItemDescription Version 1
|
||||
type BaseMerchantItemDescriptionV1 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
Adornment common.EQ2String16 `eq2:"string16"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
FirstDesc common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint32 `eq2:"int32"`
|
||||
Unknown81M []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStat `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseMerchantItemDescription Version 860
|
||||
type BaseMerchantItemDescriptionV860 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
Adornment common.EQ2String16 `eq2:"string16"`
|
||||
Unknown3 []uint32 `eq2:"int32,len=2"`
|
||||
AdornmentDesc common.EQ2String16 `eq2:"string16"`
|
||||
UnknownDesc common.EQ2String16 `eq2:"string16"`
|
||||
FirstDesc common.EQ2String16 `eq2:"string16"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint32 `eq2:"int32"`
|
||||
Unknown8860M []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatMerchant860 `eq2:"array,arraysize=StatCount"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatString `eq2:"array,arraysize=StatStringCount"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseMerchantItemDescription Version 1096
|
||||
type BaseMerchantItemDescriptionV1096 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown81096M []uint8 `eq2:"int8,len=17"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatMerchant1096 `eq2:"array,arraysize=StatCount"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringMerchant1096 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
Unknown20 uint16 `eq2:"int16"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// BaseMerchantItemDescription Version 63119
|
||||
type BaseMerchantItemDescriptionV63119 struct {
|
||||
CreatorFlag uint8 `eq2:"int8"`
|
||||
Creator common.EQ2String8 `eq2:"string8"`
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
ItemCRC int32 `eq2:"sint32"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
Flags uint16 `eq2:"int16"`
|
||||
Flags2 uint16 `eq2:"int16"`
|
||||
Unknown8 []uint8 `eq2:"int8,len=21"`
|
||||
StatCount uint8 `eq2:"int8"`
|
||||
StatArray []BaseItemStatMerchant63119 `eq2:"array,arraysize=StatCount"`
|
||||
StatUnknown uint8 `eq2:"int8"`
|
||||
StatStringCount uint8 `eq2:"int8"`
|
||||
StatStringArray []BaseItemStatStringMerchant63119 `eq2:"array,arraysize=StatStringCount"`
|
||||
Unknown19 uint16 `eq2:"int16"`
|
||||
Unknown20 uint16 `eq2:"int16"`
|
||||
Condition uint8 `eq2:"int8"`
|
||||
Weight uint32 `eq2:"int32"`
|
||||
SkillReq1 uint32 `eq2:"int32"`
|
||||
SkillReq2 uint32 `eq2:"int32"`
|
||||
SkillMin uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
ClassCount uint8 `eq2:"int8"`
|
||||
ClassArray []BaseItemClass `eq2:"array,arraysize=ClassCount"`
|
||||
SlotCount uint8 `eq2:"int8"`
|
||||
SlotArray []uint8 `eq2:"array,arraysize=SlotCount"`
|
||||
FooterType uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
// Merchant-specific stat structs
|
||||
type BaseItemStatMerchant860 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
Value int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatMerchant1096 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
Value any `eq2:"float,type2=sint16,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type BaseItemStatMerchant63119 struct {
|
||||
StatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
StatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=stat_type_%i"`
|
||||
Value any `eq2:"float,type2=sint32,type2criteria=stat_type!=6"`
|
||||
StatName common.EQ2String8 `eq2:"string8"`
|
||||
StatLevel any `eq2:"int16,type2=int8,type2criteria=stat_name!>2"`
|
||||
Value2 float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringMerchant1096 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type BaseItemStatStringMerchant63119 struct {
|
||||
StatString common.EQ2String8 `eq2:"string8"`
|
||||
StatStringUnknown uint8 `eq2:"int8"`
|
||||
StatDescription common.EQ2String16 `eq2:"string16"`
|
||||
}
|
@ -1,193 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// GroupMember Version 1
|
||||
type GroupMemberV1 struct {
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Name []byte `eq2:"char,len=16"`
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
HPCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// GroupMember Version 373
|
||||
type GroupMemberV373 struct {
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Name []byte `eq2:"char,len=16"`
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
HPCurrent int32 `eq2:"sint32"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// GroupMember Version 546
|
||||
type GroupMemberV546 struct {
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
HPCurrent int32 `eq2:"sint32"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// GroupMember Version 562
|
||||
type GroupMemberV562 struct {
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
HPCurrent int32 `eq2:"sint32"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Unknown4 uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
CurseCount uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
}
|
||||
|
||||
// GroupMember Version 1188
|
||||
type GroupMemberV1188 struct {
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
HPCurrent int32 `eq2:"sint32"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Unknown4 uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
CurseCount uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
CoEUnknown []uint8 `eq2:"int8,len=9"`
|
||||
}
|
||||
|
||||
// GroupMember Version 57048
|
||||
type GroupMemberV57048 struct {
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
HPCurrent int64 `eq2:"sint64"`
|
||||
HPMax int64 `eq2:"sint64"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Unknown4 uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
CurseCount uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
CoEUnknown []uint8 `eq2:"int8,len=9"`
|
||||
}
|
||||
|
||||
// GroupMember Version 61532
|
||||
type GroupMemberV61532 struct {
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
HPCurrent int64 `eq2:"sint64"`
|
||||
HPCurrent2 int64 `eq2:"sint64"`
|
||||
HPMax int32 `eq2:"sint32"`
|
||||
HPMax2 int32 `eq2:"sint32"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Unknown4 uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
CurseCount uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
CoEUnknown []uint8 `eq2:"int8,len=9"`
|
||||
}
|
||||
|
||||
// GroupMember Version 63167
|
||||
type GroupMemberV63167 struct {
|
||||
SpawnID uint32 `eq2:"int32"`
|
||||
PetID uint32 `eq2:"int32"`
|
||||
HPCurrent int64 `eq2:"sint64"`
|
||||
HPMax int64 `eq2:"sint64"`
|
||||
PowerCurrent int32 `eq2:"sint32"`
|
||||
PowerMax int32 `eq2:"sint32"`
|
||||
LevelCurrent uint16 `eq2:"int16"`
|
||||
LevelMax uint16 `eq2:"int16"`
|
||||
Name []byte `eq2:"char,len=41"`
|
||||
Zone []byte `eq2:"char,len=60"`
|
||||
Instance uint8 `eq2:"int8"`
|
||||
ZoneStatus uint8 `eq2:"int8"`
|
||||
Unknown4 uint16 `eq2:"int16"`
|
||||
RaceID uint8 `eq2:"int8"`
|
||||
ClassID uint8 `eq2:"int8"`
|
||||
TraumaCount uint8 `eq2:"int8"`
|
||||
ArcaneCount uint8 `eq2:"int8"`
|
||||
NoxiousCount uint8 `eq2:"int8"`
|
||||
ElementalCount uint8 `eq2:"int8"`
|
||||
CurseCount uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
CoEUnknown []uint8 `eq2:"int8,len=9"`
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// InfoTemplate Version 63119
|
||||
type InfoTemplate struct {
|
||||
NumTabs uint16 `eq2:"int16"`
|
||||
TabTemplateArray []TabTemplate `eq2:"array,arraysize=NumTabs"`
|
||||
}
|
||||
|
||||
type TabTemplate struct {
|
||||
TabNumber uint16 `eq2:"int16"`
|
||||
TabUnknown1 uint32 `eq2:"int32"`
|
||||
TemplateSize uint16 `eq2:"int16"`
|
||||
TemplateArray []TemplateData `eq2:"array,arraysize=TemplateSize"`
|
||||
}
|
||||
|
||||
type TemplateData struct {
|
||||
TemplatePos uint16 `eq2:"int16"`
|
||||
TemplateUnknown3 uint16 `eq2:"int16"`
|
||||
TemplateID uint32 `eq2:"int32"`
|
||||
}
|
@ -1,207 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// Item Version 1
|
||||
type ItemV1 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Unknown uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=81"`
|
||||
}
|
||||
|
||||
// Item Version 373
|
||||
type ItemV373 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Level uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 562
|
||||
type ItemV562 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 893
|
||||
type ItemV893 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3b uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 1193
|
||||
type ItemV1193 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3b uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=18"`
|
||||
}
|
||||
|
||||
// Item Version 1205
|
||||
type ItemV1205 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3b uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint8 `eq2:"int8"`
|
||||
Unknown4 uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 57048
|
||||
type ItemV57048 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3b uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint16 `eq2:"int16"`
|
||||
Unknown4b uint8 `eq2:"int8"`
|
||||
Unknown4c uint8 `eq2:"int8"`
|
||||
ItemLevel uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 57107
|
||||
type ItemV57107 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3b uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint16 `eq2:"int16"`
|
||||
Unknown4b uint8 `eq2:"int8"`
|
||||
Unknown4c uint8 `eq2:"int8"`
|
||||
ItemLevel uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
Unknown5 []uint8 `eq2:"int8,len=2"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
BrokerID uint64 `eq2:"int64"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 63119
|
||||
type ItemV63119 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint16 `eq2:"int16"`
|
||||
Unknown4b uint8 `eq2:"int8"`
|
||||
Unknown4c uint8 `eq2:"int8"`
|
||||
ItemLevel uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
EmptySlots uint8 `eq2:"int8"`
|
||||
Unknown52 uint8 `eq2:"int8"`
|
||||
Unknown53 uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
BrokerID uint64 `eq2:"int64"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
||||
|
||||
// Item Version 63214 (latest)
|
||||
type ItemV63214 struct {
|
||||
UniqueID uint32 `eq2:"int32"`
|
||||
BagID uint32 `eq2:"int32"`
|
||||
InvSlotID uint32 `eq2:"int32"`
|
||||
MenuType uint32 `eq2:"int32"`
|
||||
Unknown3 uint32 `eq2:"int32"`
|
||||
Index uint16 `eq2:"int16"`
|
||||
Icon uint16 `eq2:"int16"`
|
||||
SlotID uint8 `eq2:"int8"`
|
||||
Count uint16 `eq2:"int16"`
|
||||
Unknown4b uint8 `eq2:"int8"`
|
||||
Unknown4c uint8 `eq2:"int8"`
|
||||
ItemLevel uint8 `eq2:"int8"`
|
||||
Tier uint8 `eq2:"int8"`
|
||||
NumSlots uint8 `eq2:"int8"`
|
||||
EmptySlots uint8 `eq2:"int8"`
|
||||
Unknown52 uint8 `eq2:"int8"`
|
||||
ItemID int32 `eq2:"sint32"`
|
||||
BrokerID uint64 `eq2:"int64"`
|
||||
Name []byte `eq2:"char,len=64"`
|
||||
Unknown6 []uint8 `eq2:"int8,len=17"`
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// ItemDescription Version 1
|
||||
type ItemDescriptionV1 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV1 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 373
|
||||
type ItemDescriptionV373 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV373 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 546
|
||||
type ItemDescriptionV546 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV546 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 1096
|
||||
type ItemDescriptionV1096 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV1096 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 1188
|
||||
type ItemDescriptionV1188 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV1188 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 1208
|
||||
type ItemDescriptionV1208 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV1208 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// ItemDescription Version 63119
|
||||
type ItemDescriptionV63119 struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionV63119 `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
// WSExamineInfoHeader - referenced by ItemDescription structs
|
||||
// This struct definition needs to be provided based on the actual WS_ExamineInfoHeader definition
|
||||
type WSExamineInfoHeader struct {
|
||||
// Fields need to be defined based on actual WS_ExamineInfoHeader structure
|
||||
// Placeholder - replace with actual fields
|
||||
Unknown1 uint32 `eq2:"int32"`
|
||||
Unknown2 uint16 `eq2:"int16"`
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// ItemDescriptionGeneric Version 373
|
||||
type ItemDescriptionGeneric struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionGeneric `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// ItemDescriptionInspect Version 373
|
||||
type ItemDescriptionInspect struct {
|
||||
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
|
||||
Info BaseItemDescriptionInspect `eq2:"substruct"`
|
||||
ItemType uint8 `eq2:"int8"`
|
||||
}
|
@ -1,818 +0,0 @@
|
||||
package substructs
|
||||
|
||||
import "eq2emu/internal/common"
|
||||
|
||||
// Supporting structs for nested arrays
|
||||
type EffectItem struct {
|
||||
SubBulletFlag uint8 `eq2:"int8"`
|
||||
Effect common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type EffectItemV546 struct {
|
||||
SubBulletFlag uint8 `eq2:"int8"`
|
||||
Effect common.EQ2String16 `eq2:"string16"`
|
||||
Percentage uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SetStatItem struct {
|
||||
SetStatType uint8 `eq2:"int8"`
|
||||
SetStatSubtype uint8 `eq2:"int8"`
|
||||
SetValue int16 `eq2:"sint16,oversized=127,oversizedbyte=127"`
|
||||
SetStatName common.EQ2String8 `eq2:"string8"`
|
||||
}
|
||||
|
||||
type SetStatItemV1188 struct {
|
||||
SetStatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SetStatSubtype uint16 `eq2:"int16,oversized=127,oversizedbyte=127,ifnotequals=set_stat_type_%i"`
|
||||
SetValue any `eq2:"float,type2=sint16,type2criteria=set_stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
SetStatName common.EQ2String8 `eq2:"string8"`
|
||||
SetStatUnknown uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SetStatItemV63119 struct {
|
||||
SetStatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
SetStatSubtype uint16 `eq2:"int16,oversized=127,oversizedbyte=127,ifnotequals=set_stat_type_%i"`
|
||||
SetValue any `eq2:"float,type2=sint32,type2criteria=set_stat_type!=6"`
|
||||
SetStatName common.EQ2String8 `eq2:"string8"`
|
||||
SetStatUnknown uint32 `eq2:"int32"`
|
||||
SetStatUnknownMJ uint16 `eq2:"int16"`
|
||||
}
|
||||
|
||||
type SetEffectItem struct {
|
||||
SetSubBulletFlag uint8 `eq2:"int8"`
|
||||
SetEffect common.EQ2String16 `eq2:"string16"`
|
||||
SetPercentage uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SetBonusItem struct {
|
||||
SetNumNeeded uint8 `eq2:"int8"`
|
||||
SetStatCount uint8 `eq2:"int8"`
|
||||
SetStatArray []SetStatItem `eq2:"array,arraysize=SetStatCount"`
|
||||
NumSetEffects uint8 `eq2:"int8"`
|
||||
SetEffectArray []SetEffectItem `eq2:"array,arraysize=NumSetEffects"`
|
||||
}
|
||||
|
||||
type SetBonusItemV1188 struct {
|
||||
SetBonusItemsNeeded uint8 `eq2:"int8"`
|
||||
SetBonusStatsCount uint8 `eq2:"int8"`
|
||||
SetBonusStatsArray []SetStatItemV1188 `eq2:"array,arraysize=SetBonusStatsCount"`
|
||||
SetBonusEffectsCount uint8 `eq2:"int8"`
|
||||
SetBonusEffectsArray []SetBonusEffectItem `eq2:"array,arraysize=SetBonusEffectsCount"`
|
||||
}
|
||||
|
||||
type SetBonusItemV63119 struct {
|
||||
SetBonusItemsNeeded uint8 `eq2:"int8"`
|
||||
SetBonusStatsCount uint8 `eq2:"int8"`
|
||||
SetBonusStatsArray []SetStatItemV63119 `eq2:"array,arraysize=SetBonusStatsCount"`
|
||||
SetBonusEffectsCount uint8 `eq2:"int8"`
|
||||
SetBonusEffectsArray []SetBonusEffectItem `eq2:"array,arraysize=SetBonusEffectsCount"`
|
||||
}
|
||||
|
||||
type SetBonusEffectItem struct {
|
||||
SetBonusEffectSubBulletFlag uint8 `eq2:"int8"`
|
||||
SetBonusEffectText common.EQ2String16 `eq2:"string16"`
|
||||
SetBonusEffectPercentage uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SetItemsItem struct {
|
||||
SetItemsUnknown1 uint8 `eq2:"int8"`
|
||||
SetItemsUnknown2 uint8 `eq2:"int8"`
|
||||
SetItemName common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type AdornItem struct {
|
||||
AdornSlot uint8 `eq2:"int8"`
|
||||
AdornUnknown uint32 `eq2:"int32"`
|
||||
AdornName common.EQ2String16 `eq2:"string16"`
|
||||
AdornTimeLeft float32 `eq2:"float"`
|
||||
}
|
||||
|
||||
type AdornItemV1188 struct {
|
||||
AdornUnknown1 uint8 `eq2:"int8"`
|
||||
AdornSlot uint8 `eq2:"int8"`
|
||||
AdornUnknown2 []uint8 `eq2:"int8,len=2"`
|
||||
AdornItemID uint32 `eq2:"int32"`
|
||||
AdornName common.EQ2String16 `eq2:"string16"`
|
||||
AdornTimeLeft float32 `eq2:"float"`
|
||||
AdornUnknown3 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
type AdornItemV63119 struct {
|
||||
AdornSlot uint8 `eq2:"int8"`
|
||||
AdornUnknown1 uint8 `eq2:"int8"`
|
||||
AdornUnknown2 []uint8 `eq2:"int8,len=2"`
|
||||
AdornItemID uint32 `eq2:"int32"`
|
||||
AdornName common.EQ2String16 `eq2:"string16"`
|
||||
AdornTimeLeft float32 `eq2:"float"`
|
||||
AdornUnknown3 uint32 `eq2:"int32"`
|
||||
}
|
||||
|
||||
type AdornStatItem struct {
|
||||
AdornStatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
AdornStatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=adorn_stat_type_%i_%i"`
|
||||
AdornValue any `eq2:"float,type2=sint16,type2criteria=stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
AdornStatName common.EQ2String8 `eq2:"string8"`
|
||||
AdornStatLevel uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type AdornStatItemV63119 struct {
|
||||
AdornStatType uint16 `eq2:"int16,oversized=127,oversizedbyte=127"`
|
||||
AdornStatSubtype int16 `eq2:"sint16,oversized=127,oversizedbyte=127,ifnotequals=adorn_stat_type_%i_%i"`
|
||||
AdornValue any `eq2:"float,type2=sint32,type2criteria=adorn_stat_type!=6,oversized=127,oversizedbyte=127"`
|
||||
AdornStatName common.EQ2String8 `eq2:"string8"`
|
||||
AdornStatLevel uint8 `eq2:"int8"`
|
||||
AdornStatUnknown1 []uint8 `eq2:"int8,len=5"`
|
||||
}
|
||||
|
||||
type AdornLevelItem struct {
|
||||
NumAdornStats uint32 `eq2:"int32"`
|
||||
AdornStatsArray []AdornStatItem `eq2:"array,arraysize=NumAdornStats"`
|
||||
}
|
||||
|
||||
type AdornLevelItemV63119 struct {
|
||||
NumAdornStats uint32 `eq2:"int32"`
|
||||
AdornStatsArray []AdornStatItemV63119 `eq2:"array,arraysize=NumAdornStats"`
|
||||
}
|
||||
|
||||
type TierlineItem struct {
|
||||
Addon common.EQ2String16 `eq2:"string16"`
|
||||
TierlineUnknown []uint8 `eq2:"int8,len=5"`
|
||||
}
|
||||
|
||||
// Version structs
|
||||
type SubstructItemFooterV1 struct {
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV373 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifflagnotset=loot"`
|
||||
EffectArray []EffectItem `eq2:"array,arraysize=NumEffects,ifflagnotset=loot"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV546 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifflagnotset=loot"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects,ifflagnotset=loot"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV562 struct {
|
||||
// NOTE: Parser needs enhancement for comma-separated conditions
|
||||
// Original: IfVariableNotSet="header_info_header_unknown_0_0,header_unknown_0"
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo uint32 `eq2:"int32,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info2_0"`
|
||||
DisplayCharges uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV860 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo uint32 `eq2:"int32,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info2_0"`
|
||||
FooterUnknown5 uint8 `eq2:"int8"`
|
||||
DisplayCharges uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV893 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
FooterUnknown3 uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo uint32 `eq2:"int32,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info2_0"`
|
||||
FooterUnknown5 uint8 `eq2:"int8"`
|
||||
DisplayCharges uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV927 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
FooterUnknown3 uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo uint32 `eq2:"int32,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info2_0"`
|
||||
FooterUnknown5 uint8 `eq2:"int8"`
|
||||
DisplayCharges uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV1027 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
FooterUnknown3 []uint8 `eq2:"int8,len=2"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
FooterUnknown4 []uint8 `eq2:"int8,len=4"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo uint32 `eq2:"int32,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info2_0"`
|
||||
FooterUnknown5 []uint8 `eq2:"int8,len=2"`
|
||||
DisplayCharges uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV1096 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint8 `eq2:"int8"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
FooterUnknown3 uint8 `eq2:"int8"`
|
||||
FooterUnknown3A uint8 `eq2:"int8"`
|
||||
FooterUnknown3B uint8 `eq2:"int8"`
|
||||
FooterUnknown3C uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
NumSets uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetArray []SetBonusItem `eq2:"array,arraysize=NumSets"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem uint8 `eq2:"int8"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlagXXX uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItem `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV1188 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=6"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
FooterUnknown4A uint8 `eq2:"int8,ifvariableset=footer_footer_unknown4_0"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 []uint8 `eq2:"int8,len=3,ifvariableset=footer_set_name_0"`
|
||||
StatusItem []uint8 `eq2:"int8,len=2"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6 uint8 `eq2:"int8"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV57048 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=6"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem []uint8 `eq2:"int8,len=2"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6 []uint8 `eq2:"int8,len=13"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV58571 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem []uint8 `eq2:"int8,len=2"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6 []uint8 `eq2:"int8,len=15"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknownVer58571 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV58617 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8"` // Note: XML comment indicates removing ifvariablenotset condition
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem []uint8 `eq2:"int8,len=2"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
Unknown58617_1_MJ uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6 []uint8 `eq2:"int8,len=17"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknownVer58617 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV60024 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem uint8 `eq2:"int8"`
|
||||
Unknown60024A uint8 `eq2:"int8"`
|
||||
Unknown60024B []uint8 `eq2:"int8,len=4,ifvariableset=footer_unknown60024a_0"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6 []uint8 `eq2:"int8,len=18"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV60055 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Unknown60055ZA uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
Unknown60055Z uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownEmem1 uint8 `eq2:"int8"`
|
||||
UnknownEmem2 uint8 `eq2:"int8"`
|
||||
UnknownEmem3 uint8 `eq2:"int8"`
|
||||
UnknownEmem4 uint8 `eq2:"int8"`
|
||||
StatusItem uint32 `eq2:"int32"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6A uint8 `eq2:"int8"`
|
||||
FooterUnknown6B uint8 `eq2:"int8"`
|
||||
FooterUnknown6C uint8 `eq2:"int8"`
|
||||
FooterUnknown6D uint8 `eq2:"int8"`
|
||||
FooterUnknown6E uint8 `eq2:"int8"`
|
||||
FooterUnknown6F uint8 `eq2:"int8"`
|
||||
FooterUnknown6G uint8 `eq2:"int8"`
|
||||
FooterUnknown6H uint8 `eq2:"int8"`
|
||||
FooterUnknown6I uint8 `eq2:"int8"`
|
||||
FooterUnknown6J uint8 `eq2:"int8"`
|
||||
FooterUnknown6K uint8 `eq2:"int8"`
|
||||
FooterUnknown6L uint8 `eq2:"int8"`
|
||||
FooterUnknown6M uint8 `eq2:"int8"`
|
||||
FooterUnknown6N uint8 `eq2:"int8"`
|
||||
FooterUnknown6O uint8 `eq2:"int8"`
|
||||
FooterUnknown6 []uint8 `eq2:"int8,len=2"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV60174 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
FooterUnknown2 uint8 `eq2:"int8"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV1188 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItem `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Unknown60055ZA uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
Collectable uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
Unknown60055Z uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8,ifvariablenotset=footer_set_name_0"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
StatusItem uint32 `eq2:"int32"`
|
||||
Unknown60024A uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
AdornArray []AdornItemV1188 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6A uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
FooterUnknown6B []uint8 `eq2:"int8,len=21"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
||||
|
||||
type SubstructItemFooterV63119 struct {
|
||||
NumEffects uint8 `eq2:"int8,ifvariablenotset=header_info_header_unknown_0_0"`
|
||||
EffectArray []EffectItemV546 `eq2:"array,arraysize=NumEffects"`
|
||||
Tierline uint8 `eq2:"int8"`
|
||||
TierlineArray []TierlineItem `eq2:"array,arraysize=Tierline"`
|
||||
RequiredClasses uint64 `eq2:"int64"`
|
||||
RequiredClasses2 uint64 `eq2:"int64"`
|
||||
RecommendedLevel uint8 `eq2:"int8"`
|
||||
RequiredLevel uint8 `eq2:"int8"`
|
||||
StackSize uint16 `eq2:"int16"`
|
||||
AdornSlots []uint8 `eq2:"int8,len=11"`
|
||||
FooterUnknown3MJ1 uint8 `eq2:"int8"`
|
||||
SetName common.EQ2String8 `eq2:"string8"`
|
||||
SetBonusListCount uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetBonusListArray []SetBonusItemV63119 `eq2:"array,arraysize=SetBonusListCount"`
|
||||
NumItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
SetItemsArray []SetItemsItem `eq2:"array,arraysize=NumItemsInSet"`
|
||||
TotalSetItemsEquipped uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
TotalSetItemsInSet uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
AdornFlag uint8 `eq2:"int8"`
|
||||
AdornUnknown64A uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornUnknown64B uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsActive uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsTotal uint8 `eq2:"int8,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornName common.EQ2String16 `eq2:"string16,ifvariableset=footer_adorn_flag_0"`
|
||||
NumAdornLevels uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornStatsUnknown1 uint32 `eq2:"int32,ifvariableset=footer_adorn_flag_0"`
|
||||
AdornLevelArray []AdornLevelItemV63119 `eq2:"array,arraysize=NumAdornLevels"`
|
||||
FooterUnknown4 uint8 `eq2:"int8"`
|
||||
Unknown60055ZA uint8 `eq2:"int8,ifvariableset=foot_set_name_0"`
|
||||
Collectable uint8 `eq2:"int8"`
|
||||
CollectionNeeded uint8 `eq2:"int8,ifvariableset=footer_collectable_0"`
|
||||
Unknown60055Z uint8 `eq2:"int8"`
|
||||
OffersQuest common.EQ2String8 `eq2:"string8"`
|
||||
PartOfQuest common.EQ2String8 `eq2:"string8"`
|
||||
OffersQuestColor uint8 `eq2:"int8,ifvariableset=footer_offers_quest_0"`
|
||||
PartOfQuestColor uint8 `eq2:"int8,ifvariableset=footer_part_of_quest_0"`
|
||||
UnknownSetData1 []uint8 `eq2:"int8,len=2,ifvariableset=footer_set_name_0"`
|
||||
Charges uint8 `eq2:"int8"`
|
||||
TotalCharges uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
ChargesLeft uint16 `eq2:"int16,ifvariableset=footer_charges_0"`
|
||||
UnknownSetInfo2 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownSetInfo3A uint32 `eq2:"int32,ifvariableset=footer_unknown_set_info3_0"`
|
||||
UnknownSetInfo4 uint8 `eq2:"int8,ifvariableset=footer_set_name_0"`
|
||||
UnknownEmem1 []uint8 `eq2:"int8,len=4"`
|
||||
StatusItem uint32 `eq2:"int32"`
|
||||
Unknown60024B uint8 `eq2:"int8"`
|
||||
TransmutedFlag uint8 `eq2:"int8"`
|
||||
UnknownMJ38A uint8 `eq2:"int8"`
|
||||
UnknownMJ38B uint8 `eq2:"int8"`
|
||||
CraftingFlag uint8 `eq2:"int8"`
|
||||
UnknownMJ38D uint8 `eq2:"int8"`
|
||||
AdornCount uint8 `eq2:"int8"`
|
||||
AdornArray []AdornItemV63119 `eq2:"array,arraysize=AdornCount"`
|
||||
LockedFlag uint8 `eq2:"int8"`
|
||||
UnknownMJ38C uint8 `eq2:"int8"`
|
||||
AccountRestricted uint8 `eq2:"int8"`
|
||||
FooterUnknown6B []uint8 `eq2:"int8,len=7"`
|
||||
FooterUnknown6C uint32 `eq2:"int32,ifvariablenotset=footer_set_name_0"`
|
||||
FooterUnknown6D uint8 `eq2:"int8,ifvariablenotset=footer_set_name_0"`
|
||||
Name common.EQ2String8 `eq2:"string8"`
|
||||
Description common.EQ2String16 `eq2:"string16"`
|
||||
FooterUnknown7 uint8 `eq2:"int8"`
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
package substructs
|
||||
|
||||
// ItemInfo Version 63119
|
||||
type ItemInfo struct {
|
||||
NumItems uint16 `eq2:"int16"`
|
||||
ItemsArray []ItemIndex `eq2:"array,arraysize=NumItems"`
|
||||
}
|
||||
|
||||
type ItemIndex struct {
|
||||
ItemIndex uint16 `eq2:"int16"`
|
||||
TabUnknown2 uint32 `eq2:"int32"`
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user