2025-07-27 22:16:36 -05:00

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