85 lines
2.1 KiB
Go
85 lines
2.1 KiB
Go
package parser
|
|
|
|
import "eq2emu/internal/common"
|
|
|
|
func (def *PacketDef) Parse(data []byte, version uint32, flags uint64) (map[string]any, error) {
|
|
ctx := NewContext(data, version, flags)
|
|
return def.parseStruct(ctx)
|
|
}
|
|
|
|
func (def *PacketDef) parseStruct(ctx *ParseContext) (map[string]any, error) {
|
|
result := make(map[string]any)
|
|
order := def.getVersionOrder(ctx.version)
|
|
|
|
for _, fieldName := range order {
|
|
field := def.Fields[fieldName]
|
|
|
|
if !ctx.checkCondition(field.Condition) {
|
|
continue
|
|
}
|
|
|
|
fieldType := field.Type
|
|
if field.Type2 != 0 && ctx.checkCondition(field.Type2Cond) {
|
|
fieldType = field.Type2
|
|
}
|
|
|
|
value := def.parseField(ctx, field, fieldType, fieldName)
|
|
result[fieldName] = value
|
|
ctx.setVar(fieldName, value)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (def *PacketDef) parseField(ctx *ParseContext, field FieldDesc, fieldType common.EQ2DataType, fieldName string) any {
|
|
switch fieldType {
|
|
case common.TypeInt8, common.TypeSInt8:
|
|
if field.Oversized > 0 {
|
|
return ctx.readOversizedUint8(field.Oversized)
|
|
}
|
|
return ctx.readUint8()
|
|
case common.TypeInt16, common.TypeSInt16:
|
|
if field.Oversized > 0 {
|
|
return ctx.readOversizedUint16(field.Oversized)
|
|
}
|
|
return ctx.readUint16()
|
|
case common.TypeInt32, common.TypeSInt32:
|
|
return ctx.readUint32()
|
|
case common.TypeString8:
|
|
return ctx.readEQ2String8()
|
|
case common.TypeString16:
|
|
return ctx.readEQ2String16()
|
|
case common.TypeString32:
|
|
return ctx.readEQ2String32()
|
|
case common.TypeChar:
|
|
return ctx.readBytes(field.Length)
|
|
case common.TypeFloat:
|
|
return ctx.readFloat32()
|
|
case common.TypeColor:
|
|
return ctx.readEQ2Color()
|
|
case common.TypeEquipment:
|
|
return ctx.readEQ2Equipment()
|
|
case common.TypeArray:
|
|
size := ctx.getArraySize(field.Condition)
|
|
result := make([]map[string]any, size)
|
|
for i := 0; i < size; i++ {
|
|
ctx.pushArrayIndex(i)
|
|
item, _ := field.SubDef.parseStruct(ctx)
|
|
result[i] = item
|
|
ctx.popArrayIndex()
|
|
}
|
|
return result
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (def *PacketDef) getVersionOrder(version uint32) []string {
|
|
var bestVersion uint32
|
|
for v := range def.Orders {
|
|
if v <= version && v > bestVersion {
|
|
bestVersion = v
|
|
}
|
|
}
|
|
return def.Orders[bestVersion]
|
|
}
|