remove packet parser

This commit is contained in:
Sky Johnson 2025-07-27 21:29:16 -05:00
parent 35fc2b667b
commit c5a5786400
38 changed files with 0 additions and 7187 deletions

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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{}))
}

View File

@ -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)
}
}

View File

@ -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` |

View File

@ -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
}

View File

@ -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
}

View File

@ -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,
}
}

View File

@ -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
}

View File

@ -1,243 +0,0 @@
package parser
import (
"encoding/binary"
"fmt"
"io"
"reflect"
"unsafe"
)
// Parser handles reading EQ2 packet data into structs
type Parser struct {
data []byte
offset int
endian binary.ByteOrder
fieldCache map[string]any
currentStruct reflect.Value
flags map[string]bool
structStack []reflect.Value
arrayStack []ArrayContext
}
// ArrayContext tracks array parsing state
type ArrayContext struct {
elementType reflect.Type
currentIndex int
totalSize int
sizeVariable string
}
// NewParser creates a new EQ2 packet parser
func NewParser(data []byte) *Parser {
return &Parser{
data: data,
offset: 0,
endian: binary.LittleEndian,
fieldCache: make(map[string]any),
flags: make(map[string]bool),
structStack: make([]reflect.Value, 0),
arrayStack: make([]ArrayContext, 0),
}
}
// SetFlag sets a flag for conditional parsing
func (p *Parser) SetFlag(name string, value bool) {
p.flags[name] = value
}
// ParseStruct reads data into a struct using reflection and tags
func (p *Parser) ParseStruct(v any) error {
val := reflect.ValueOf(v)
if val.Kind() != reflect.Ptr || val.Elem().Kind() != reflect.Struct {
return fmt.Errorf("target must be pointer to struct")
}
elem := val.Elem()
typ := elem.Type()
p.currentStruct = elem
p.fieldCache = make(map[string]any)
for i := 0; i < elem.NumField(); i++ {
field := elem.Field(i)
fieldType := typ.Field(i)
if !field.CanSet() {
continue
}
tag := fieldType.Tag.Get("eq2")
if tag == "" || tag == "-" {
continue
}
if err := p.parseField(field, tag); err != nil {
return fmt.Errorf("field %s: %w", fieldType.Name, err)
}
if field.CanInterface() {
p.fieldCache[fieldType.Name] = field.Interface()
}
}
return nil
}
// parseField processes individual struct fields based on their tags
func (p *Parser) parseField(field reflect.Value, tag string) error {
fieldTag := p.parseFieldTag(tag)
if !p.evaluateAllConditions(fieldTag, field) {
return nil
}
length := fieldTag.Length
if fieldTag.DynamicLen != "" {
if dynLen := p.getDynamicLength(fieldTag.DynamicLen); dynLen > 0 {
length = dynLen
if fieldTag.MaxSize > 0 && length > fieldTag.MaxSize {
if fieldTag.SkipOversized {
length = fieldTag.MaxSize
} else {
return fmt.Errorf("length %d exceeds maximum %d", length, fieldTag.MaxSize)
}
}
}
}
if fieldTag.OversizedValue > 0 && length > fieldTag.OversizedValue {
if fieldTag.SkipOversized {
length = fieldTag.OversizedValue
} else {
return p.handleOversizedField(field, fieldTag.OversizedByte, length)
}
}
actualType := fieldTag.Type
if fieldTag.Type2 != "" && fieldTag.Type2Criteria != "" {
if p.evaluateType2Criteria(fieldTag.Type2Criteria) {
actualType = fieldTag.Type2
}
}
return p.parseFieldByType(field, actualType, length, fieldTag)
}
// parseFieldByType handles type-specific parsing
func (p *Parser) parseFieldByType(field reflect.Value, fieldType string, length int, fieldTag *FieldTag) error {
switch fieldType {
case "int8":
return p.readInt8(field, length)
case "int16":
return p.readInt16(field, length)
case "int32":
return p.readInt32(field, length)
case "int64":
return p.readInt64(field, length)
case "sint8":
return p.readSInt8(field, length)
case "sint16":
return p.readSInt16(field, length)
case "sint32":
return p.readSInt32(field, length)
case "sint64":
return p.readSInt64(field, length)
case "char":
return p.readChar(field, length)
case "float":
return p.readFloat(field, length)
case "double":
return p.readDouble(field, length)
case "string8", "EQ2_8BitString", "EQ2_8Bit_String":
return p.readString8(field)
case "string16", "EQ2_16BitString", "EQ2_16Bit_String":
return p.readString16(field)
case "string32", "EQ2_32BitString", "EQ2_32Bit_String":
return p.readString32(field)
case "color", "EQ2_Color":
return p.readColor(field, length)
case "equipment", "EQ2_EquipmentItem":
return p.readEquipment(field, length)
case "array":
return p.readArray(field, fieldTag)
case "substruct":
return p.readSubstruct(field, length)
default:
return fmt.Errorf("unknown type: %s", fieldType)
}
}
// Low-level read methods
func (p *Parser) readUint8() (uint8, error) {
if p.offset >= len(p.data) {
return 0, io.EOF
}
val := p.data[p.offset]
p.offset++
return val, nil
}
func (p *Parser) readUint16() (uint16, error) {
if p.offset+2 > len(p.data) {
return 0, io.EOF
}
val := p.endian.Uint16(p.data[p.offset:])
p.offset += 2
return val, nil
}
func (p *Parser) readUint32() (uint32, error) {
if p.offset+4 > len(p.data) {
return 0, io.EOF
}
val := p.endian.Uint32(p.data[p.offset:])
p.offset += 4
return val, nil
}
func (p *Parser) readUint64() (uint64, error) {
if p.offset+8 > len(p.data) {
return 0, io.EOF
}
val := p.endian.Uint64(p.data[p.offset:])
p.offset += 8
return val, nil
}
func (p *Parser) readFloat32() (float32, error) {
val, err := p.readUint32()
if err != nil {
return 0, err
}
return *(*float32)(unsafe.Pointer(&val)), nil
}
func (p *Parser) readFloat64() (float64, error) {
val, err := p.readUint64()
if err != nil {
return 0, err
}
return *(*float64)(unsafe.Pointer(&val)), nil
}
func (p *Parser) readBytes(buf []byte) error {
if p.offset+len(buf) > len(p.data) {
return io.EOF
}
copy(buf, p.data[p.offset:])
p.offset += len(buf)
return nil
}
// Position tracking
func (p *Parser) Offset() int {
return p.offset
}
func (p *Parser) SetOffset(offset int) {
p.offset = offset
}
func (p *Parser) Remaining() int {
return len(p.data) - p.offset
}

View File

@ -1,424 +0,0 @@
package parser
import (
"eq2emu/internal/common"
"reflect"
"testing"
)
type BasicPacket struct {
Channel uint8 `eq2:"int8"`
Count uint16 `eq2:"int16"`
MessageType uint8 `eq2:"int8,if=Channel==1"`
}
type ArrayPacket struct {
ItemCount uint16 `eq2:"int16"`
Items []ItemDescription `eq2:"array,arraysize=ItemCount"`
}
type ItemDescription struct {
InfoHeader WS_ExamineInfoHeader `eq2:"substruct"`
Info BaseItemDescription `eq2:"substruct"`
ItemType uint8 `eq2:"int8"`
}
type WS_ExamineInfoHeader struct {
Unknown1 uint32 `eq2:"int32"`
Unknown2 uint16 `eq2:"int16"`
}
type BaseItemDescription struct {
Name common.EQ2String16 `eq2:"string16"`
Category common.EQ2String8 `eq2:"string8"`
}
type ConditionalPacket struct {
HasRewards uint8 `eq2:"int8"`
RewardData *RewardInfo `eq2:"substruct,ifvariableset=HasRewards"`
CompleteFlag uint8 `eq2:"int8"`
ClassicSound uint8 `eq2:"int8,ifvariableset=CompleteFlag"`
}
type RewardInfo struct {
RewardType uint8 `eq2:"int8"`
Amount uint32 `eq2:"int32"`
}
type OversizedPacket struct {
LargeDataCount uint16 `eq2:"int16"`
LargeData []byte `eq2:"char,len=LargeDataCount,maxsize=10,skipoversized"`
}
type TypeSwitchPacket struct {
StatType uint8 `eq2:"int8"`
StatValue any `eq2:"int32,type2=float,type2criteria=StatType!=6"`
}
type FlagPacket struct {
Equipment []common.EQ2EquipmentItem `eq2:"equipment,len=2,ifflag=has_equipment"`
Colors []common.EQ2Color `eq2:"color,len=3,ifflagnotset=no_colors"`
}
type ComplexPacket struct {
GroupCount uint8 `eq2:"int8"`
Groups []Group `eq2:"array,arraysize=GroupCount"`
}
type Group struct {
MemberCount uint16 `eq2:"int16"`
Members []Member `eq2:"array,arraysize=MemberCount"`
}
type Member struct {
Name common.EQ2String16 `eq2:"string16"`
Level uint8 `eq2:"int8"`
Class uint8 `eq2:"int8"`
}
// Version-specific structs
type PacketV1 struct {
Field1 uint8 `eq2:"int8"`
Field2 uint16 `eq2:"int16"`
}
type PacketV2 struct {
Field1 uint8 `eq2:"int8"`
Field2 uint16 `eq2:"int16"`
NewField uint32 `eq2:"int32"`
}
func TestBasicParsing(t *testing.T) {
// Basic packet: Channel=1, Count=100, MessageType=5
data := []byte{0x01, 0x64, 0x00, 0x05}
parser := NewParser(data)
var packet BasicPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.Channel != 1 {
t.Errorf("Expected Channel=1, got %d", packet.Channel)
}
if packet.Count != 100 {
t.Errorf("Expected Count=100, got %d", packet.Count)
}
if packet.MessageType != 5 {
t.Errorf("Expected MessageType=5, got %d", packet.MessageType)
}
}
func TestConditionalSkip(t *testing.T) {
// Channel=2 (not 1), so MessageType should be skipped
data := []byte{0x02, 0x64, 0x00}
parser := NewParser(data)
var packet BasicPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.Channel != 2 {
t.Errorf("Expected Channel=2, got %d", packet.Channel)
}
if packet.MessageType != 0 {
t.Errorf("Expected MessageType=0 (skipped), got %d", packet.MessageType)
}
}
func TestArrayParsing(t *testing.T) {
// ItemCount=2, then 2 items
data := []byte{
0x02, 0x00, // ItemCount = 2
// Item 1
0x01, 0x00, 0x00, 0x00, // InfoHeader.Unknown1 = 1
0x02, 0x00, // InfoHeader.Unknown2 = 2
0x04, 0x00, 't', 'e', 's', 't', // Name: "test"
0x03, 'c', 'a', 't', // Category: "cat"
0x05, // ItemType = 5
// Item 2
0x03, 0x00, 0x00, 0x00, // InfoHeader.Unknown1 = 3
0x04, 0x00, // InfoHeader.Unknown2 = 4
0x05, 0x00, 'i', 't', 'e', 'm', '2', // Name: "item2"
0x04, 't', 'y', 'p', 'e', // Category: "type"
0x06, // ItemType = 6
}
parser := NewParser(data)
var packet ArrayPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.ItemCount != 2 {
t.Errorf("Expected ItemCount=2, got %d", packet.ItemCount)
}
if len(packet.Items) != 2 {
t.Errorf("Expected 2 items, got %d", len(packet.Items))
}
if packet.Items[0].Info.Name.Data != "test" {
t.Errorf("Expected first item name 'test', got '%s'", packet.Items[0].Info.Name.Data)
}
if packet.Items[1].ItemType != 6 {
t.Errorf("Expected second item type 6, got %d", packet.Items[1].ItemType)
}
}
func TestConditionalFields(t *testing.T) {
// HasRewards=1, RewardData present, CompleteFlag=1, ClassicSound present
data := []byte{
0x01, // HasRewards = 1
0x02, // RewardType = 2
0x64, 0x00, 0x00, 0x00, // Amount = 100
0x01, // CompleteFlag = 1
0x05, // ClassicSound = 5
}
parser := NewParser(data)
var packet ConditionalPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.HasRewards != 1 {
t.Errorf("Expected HasRewards=1, got %d", packet.HasRewards)
}
if packet.RewardData == nil {
t.Error("Expected RewardData to be present")
} else {
if packet.RewardData.RewardType != 2 {
t.Errorf("Expected RewardType=2, got %d", packet.RewardData.RewardType)
}
if packet.RewardData.Amount != 100 {
t.Errorf("Expected Amount=100, got %d", packet.RewardData.Amount)
}
}
if packet.ClassicSound != 5 {
t.Errorf("Expected ClassicSound=5, got %d", packet.ClassicSound)
}
}
func TestOversizedHandling(t *testing.T) {
// LargeDataCount=15 (exceeds maxsize=10), should be truncated
data := []byte{
0x0F, 0x00, // LargeDataCount = 15
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A,
0x0B, 0x0C, 0x0D, 0x0E, 0x0F, // 15 bytes of data
}
parser := NewParser(data)
var packet OversizedPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.LargeDataCount != 15 {
t.Errorf("Expected LargeDataCount=15, got %d", packet.LargeDataCount)
}
if len(packet.LargeData) != 10 {
t.Errorf("Expected LargeData length=10 (truncated), got %d", len(packet.LargeData))
}
}
func TestTypeSwitching(t *testing.T) {
// StatType=3 (not 6), so StatValue should be parsed as float
data := []byte{
0x03, // StatType = 3
0x00, 0x00, 0x80, 0x3F, // float32: 1.0
}
parser := NewParser(data)
var packet TypeSwitchPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.StatType != 3 {
t.Errorf("Expected StatType=3, got %d", packet.StatType)
}
// Should be parsed as float32 since StatType != 6
floatVal, ok := packet.StatValue.(float32)
if !ok {
t.Errorf("Expected StatValue to be float32, got %T", packet.StatValue)
} else if floatVal != 1.0 {
t.Errorf("Expected StatValue=1.0, got %f", floatVal)
}
}
func TestFlagBasedConditionals(t *testing.T) {
// Equipment data (2 items)
data := []byte{
// Equipment item 1
0x01, 0x00, // Type = 1
0xFF, 0x00, 0x00, // Color: Red=255, Green=0, Blue=0
0x00, 0xFF, 0x00, // Highlight: Red=0, Green=255, Blue=0
// Equipment item 2
0x02, 0x00, // Type = 2
0x00, 0x00, 0xFF, // Color: Red=0, Green=0, Blue=255
0xFF, 0xFF, 0x00, // Highlight: Red=255, Green=255, Blue=0
// Colors (3 items)
0x80, 0x80, 0x80, // Color 1: Gray
0x40, 0x40, 0x40, // Color 2: Dark gray
0xC0, 0xC0, 0xC0, // Color 3: Light gray
}
parser := NewParser(data)
parser.SetFlag("has_equipment", true)
// no_colors flag is not set, so colors should be parsed
var packet FlagPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if len(packet.Equipment) != 2 {
t.Errorf("Expected 2 equipment items, got %d", len(packet.Equipment))
}
if len(packet.Colors) != 3 {
t.Errorf("Expected 3 colors, got %d", len(packet.Colors))
}
if packet.Equipment[0].Type != 1 {
t.Errorf("Expected first equipment type 1, got %d", packet.Equipment[0].Type)
}
if packet.Colors[0].Red != 0x80 {
t.Errorf("Expected first color red=128, got %d", packet.Colors[0].Red)
}
}
func TestComplexNestedArrays(t *testing.T) {
// GroupCount=1, Group has MemberCount=2
data := []byte{
0x01, // GroupCount = 1
0x02, 0x00, // MemberCount = 2
// Member 1
0x05, 0x00, 'A', 'l', 'i', 'c', 'e', // Name: "Alice"
0x0A, // Level = 10
0x01, // Class = 1
// Member 2
0x03, 0x00, 'B', 'o', 'b', // Name: "Bob"
0x0F, // Level = 15
0x02, // Class = 2
}
parser := NewParser(data)
var packet ComplexPacket
err := parser.ParseStruct(&packet)
if err != nil {
t.Fatalf("Parse error: %v", err)
}
if packet.GroupCount != 1 {
t.Errorf("Expected GroupCount=1, got %d", packet.GroupCount)
}
if len(packet.Groups) != 1 {
t.Errorf("Expected 1 group, got %d", len(packet.Groups))
}
if len(packet.Groups[0].Members) != 2 {
t.Errorf("Expected 2 members, got %d", len(packet.Groups[0].Members))
}
if packet.Groups[0].Members[0].Name.Data != "Alice" {
t.Errorf("Expected first member 'Alice', got '%s'", packet.Groups[0].Members[0].Name.Data)
}
if packet.Groups[0].Members[1].Level != 15 {
t.Errorf("Expected second member level 15, got %d", packet.Groups[0].Members[1].Level)
}
}
func TestVersionRegistry(t *testing.T) {
registry := NewVersionRegistry()
// Register different versions
registry.RegisterStruct("TestPacket", "1.0", reflect.TypeOf(PacketV1{}))
registry.RegisterStruct("TestPacket", "2.0", reflect.TypeOf(PacketV2{}))
// Test version 1.0
data1 := []byte{0x01, 0x64, 0x00} // Field1=1, Field2=100
parser1 := NewParser(data1)
result1, err := parser1.ParseWithVersion(registry, "TestPacket", "1.0")
if err != nil {
t.Fatalf("Parse v1.0 error: %v", err)
}
v1Packet, ok := result1.(PacketV1)
if !ok {
t.Fatal("Expected PacketV1 type")
}
if v1Packet.Field1 != 1 || v1Packet.Field2 != 100 {
t.Errorf("V1 packet values incorrect: Field1=%d, Field2=%d", v1Packet.Field1, v1Packet.Field2)
}
// Test version 2.0
data2 := []byte{0x02, 0xC8, 0x00, 0x90, 0x01, 0x00, 0x00} // Field1=2, Field2=200, NewField=400
parser2 := NewParser(data2)
result2, err := parser2.ParseWithVersion(registry, "TestPacket", "2.0")
if err != nil {
t.Fatalf("Parse v2.0 error: %v", err)
}
v2Packet, ok := result2.(PacketV2)
if !ok {
t.Fatal("Expected PacketV2 type")
}
if v2Packet.Field1 != 2 || v2Packet.Field2 != 200 || v2Packet.NewField != 400 {
t.Errorf("V2 packet values incorrect: Field1=%d, Field2=%d, NewField=%d",
v2Packet.Field1, v2Packet.Field2, v2Packet.NewField)
}
}
func TestVersionFallback(t *testing.T) {
registry := NewVersionRegistry()
registry.RegisterStruct("TestPacket", "1.0", reflect.TypeOf(PacketV1{}))
registry.RegisterStruct("TestPacket", "2.0", reflect.TypeOf(PacketV2{}))
// Request version 1.5 (doesn't exist), should fall back to 1.0
data := []byte{0x01, 0x64, 0x00}
parser := NewParser(data)
result, err := parser.ParseWithVersion(registry, "TestPacket", "1.5")
if err != nil {
t.Fatalf("Parse with fallback error: %v", err)
}
// Should get v1.0 (nearest lower version)
_, ok := result.(PacketV1)
if !ok {
t.Error("Expected fallback to PacketV1")
}
}
func TestParserPosition(t *testing.T) {
data := []byte{0x01, 0x02, 0x03, 0x04}
parser := NewParser(data)
if parser.Offset() != 0 {
t.Errorf("Initial offset should be 0, got %d", parser.Offset())
}
parser.readUint8() // Read one byte
if parser.Offset() != 1 {
t.Errorf("After reading 1 byte, offset should be 1, got %d", parser.Offset())
}
if parser.Remaining() != 3 {
t.Errorf("After reading 1 byte, remaining should be 3, got %d", parser.Remaining())
}
parser.SetOffset(2)
if parser.Offset() != 2 {
t.Errorf("After SetOffset(2), offset should be 2, got %d", parser.Offset())
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -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"`
}

View File

@ -1,8 +0,0 @@
package substructs
// ItemDescriptionGeneric Version 373
type ItemDescriptionGeneric struct {
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
Info BaseItemDescriptionGeneric `eq2:"substruct"`
ItemType uint8 `eq2:"int8"`
}

View File

@ -1,8 +0,0 @@
package substructs
// ItemDescriptionInspect Version 373
type ItemDescriptionInspect struct {
InfoHeader WSExamineInfoHeader `eq2:"substruct"`
Info BaseItemDescriptionInspect `eq2:"substruct"`
ItemType uint8 `eq2:"int8"`
}

View File

@ -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"`
}

View File

@ -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"`
}