diff --git a/defs/gen/main.go b/defs/gen/main.go
new file mode 100644
index 0000000..56602a0
--- /dev/null
+++ b/defs/gen/main.go
@@ -0,0 +1,821 @@
+//go:build ignore
+
+package main
+
+import (
+ "encoding/xml"
+ "flag"
+ "fmt"
+ "io"
+ "log"
+ "os"
+ "path/filepath"
+ "strings"
+ "text/template"
+)
+
+// XMLDefinition represents the root element containing structs
+type XMLDefinition struct {
+ XMLName xml.Name `xml:"structs"`
+ Structs []XMLStruct `xml:"struct"`
+}
+
+// XMLStruct represents a packet structure definition
+type XMLStruct struct {
+ Name string `xml:"name,attr"`
+ ClientVersion string `xml:"clientVersion,attr"`
+ OpcodeName string `xml:"opcodeName,attr"`
+ Fields []XMLData `xml:"data"`
+}
+
+// XMLData represents a field in the packet structure
+type XMLData struct {
+ Name string `xml:"name,attr"`
+ Type string `xml:"type,attr"`
+ Size int `xml:"size,attr"`
+ ArraySizeVariable string `xml:"arraySizeVariable,attr"`
+ IfVarSet string `xml:"ifVarSet,attr"`
+ IfVarNotSet string `xml:"ifVarNotSet,attr"`
+ OversizedValue int `xml:"oversizedValue,attr"`
+ Children []XMLData `xml:"data"` // For nested array elements
+}
+
+// TypeMapping maps XML types to Go types
+var TypeMapping = map[string]string{
+ "int8": "int8",
+ "int16": "int16",
+ "int32": "int32",
+ "int64": "int64",
+ "uint8": "uint8",
+ "uint16": "uint16",
+ "uint32": "uint32",
+ "uint64": "uint64",
+ "i8": "int8",
+ "i16": "int16",
+ "i32": "int32",
+ "i64": "int64",
+ "u8": "uint8",
+ "u16": "uint16",
+ "u32": "uint32",
+ "u64": "uint64",
+ "float": "float32",
+ "double": "float64",
+ "str8": "string",
+ "str16": "string",
+ "str32": "string",
+ "EQ2_32Bit_String": "string",
+ "EQ2_8Bit_String": "string",
+ "EQ2_16Bit_String": "string",
+ "char": "byte",
+ "color": "types.Color", // RGB color as 32-bit value
+ "equipmentItem": "types.EquipmentItem", // Custom type
+ "Array": "array", // Capital A variant
+}
+
+// GoStruct represents the generated Go struct
+type GoStruct struct {
+ Name string
+ ClientVersion string
+ OpcodeName string
+ Fields []GoField
+ PackageName string
+}
+
+// GoField represents a field in the Go struct
+type GoField struct {
+ Name string
+ GoName string
+ Type string
+ IsArray bool
+ IsDynamicArray bool
+ ArraySizeVariable string
+ Size int
+ Tag string
+ Comment string
+ IfVarSet string
+ IfVarNotSet string
+ ArrayElements []GoField // For complex array elements (anonymous struct)
+}
+
+// GenerateOutput holds the generated code
+type GenerateOutput struct {
+ SourceFile string
+ PackageName string
+ Structs []GoStruct
+ NeedsMath bool
+}
+
+// parseXMLFile parses an XML definition file
+func parseXMLFile(filename string) ([]XMLStruct, error) {
+ file, err := os.Open(filename)
+ if err != nil {
+ return nil, err
+ }
+ defer file.Close()
+
+ data, err := io.ReadAll(file)
+ if err != nil {
+ return nil, err
+ }
+
+ // Wrap content in root element if needed
+ content := string(data)
+ if !strings.HasPrefix(strings.TrimSpace(content), "") {
+ content = "" + content + ""
+ }
+
+ var def XMLDefinition
+ if err := xml.Unmarshal([]byte(content), &def); err != nil {
+ return nil, err
+ }
+
+ return def.Structs, nil
+}
+
+// toGoName converts snake_case to CamelCase
+func toGoName(name string) string {
+ parts := strings.Split(name, "_")
+ for i, part := range parts {
+ if len(part) > 0 {
+ parts[i] = strings.ToUpper(part[:1]) + part[1:]
+ }
+ }
+ return strings.Join(parts, "")
+}
+
+// mapSimpleType maps XML type to Go type
+func mapSimpleType(xmlType string) (string, bool) {
+ goType, ok := TypeMapping[xmlType]
+ if !ok {
+ return "byte", false
+ }
+ return goType, true
+}
+
+// convertArrayChildren converts nested array data to Go fields
+func convertArrayChildren(children []XMLData) []GoField {
+ fields := make([]GoField, 0, len(children))
+
+ for _, child := range children {
+ if child.Type == "array" && len(child.Children) > 0 {
+ // Nested array - recursive
+ nestedFields := convertArrayChildren(child.Children)
+ goField := GoField{
+ Name: child.Name,
+ GoName: toGoName(child.Name),
+ IsDynamicArray: true,
+ ArraySizeVariable: child.ArraySizeVariable,
+ ArrayElements: nestedFields,
+ }
+ fields = append(fields, goField)
+ } else {
+ // Simple field
+ goType, _ := mapSimpleType(child.Type)
+ isArray := child.Size > 0
+
+ goField := GoField{
+ Name: child.Name,
+ GoName: toGoName(child.Name),
+ Type: goType,
+ IsArray: isArray,
+ Size: child.Size,
+ }
+
+ if isArray {
+ goField.Type = fmt.Sprintf("[%d]%s", child.Size, goType)
+ }
+
+ fields = append(fields, goField)
+ }
+ }
+
+ return fields
+}
+
+// buildAnonymousStructType builds the anonymous struct type string
+func buildAnonymousStructType(fields []GoField) string {
+ if len(fields) == 0 {
+ return "struct{}"
+ }
+
+ var sb strings.Builder
+ sb.WriteString("struct {\n")
+ for _, field := range fields {
+ sb.WriteString("\t\t")
+ sb.WriteString(field.GoName)
+ sb.WriteString(" ")
+
+ if field.IsDynamicArray && len(field.ArrayElements) > 0 {
+ // Nested array
+ sb.WriteString("[]")
+ sb.WriteString(buildAnonymousStructType(field.ArrayElements))
+ } else if field.IsArray {
+ sb.WriteString(field.Type)
+ } else {
+ sb.WriteString(field.Type)
+ }
+
+ // Add struct tag
+ sb.WriteString(" `eq2:\"")
+ sb.WriteString(field.Name)
+ if field.Type == "string" {
+ // Determine string type from original XML
+ sb.WriteString(",type:str16") // Default to str16 for now
+ }
+ if field.IsArray && field.Size > 0 {
+ sb.WriteString(fmt.Sprintf(",size:%d", field.Size))
+ }
+ sb.WriteString("\"`")
+ sb.WriteString("\n")
+ }
+ sb.WriteString("\t}")
+ return sb.String()
+}
+
+// convertToGoStruct converts XML struct definition to Go struct
+func convertToGoStruct(xmlStruct XMLStruct, packageName string) GoStruct {
+ goStruct := GoStruct{
+ Name: toGoName(xmlStruct.Name),
+ ClientVersion: xmlStruct.ClientVersion,
+ OpcodeName: xmlStruct.OpcodeName,
+ PackageName: packageName,
+ Fields: make([]GoField, 0, len(xmlStruct.Fields)),
+ }
+
+ // Add version suffix if needed
+ if xmlStruct.ClientVersion != "" && xmlStruct.ClientVersion != "1" {
+ goStruct.Name = fmt.Sprintf("%sV%s", goStruct.Name, xmlStruct.ClientVersion)
+ }
+
+ // Track field names to avoid duplicates
+ fieldNames := make(map[string]int)
+
+ for _, field := range xmlStruct.Fields {
+ if field.Type == "array" || field.Type == "Array" {
+ // Handle array with nested structure
+ if len(field.Children) > 0 {
+ arrayElements := convertArrayChildren(field.Children)
+ structType := buildAnonymousStructType(arrayElements)
+
+ // Check for duplicate field names and make unique if needed
+ baseName := toGoName(field.Name)
+ finalName := baseName
+ if count, exists := fieldNames[baseName]; exists {
+ finalName = fmt.Sprintf("%s_%d", baseName, count+1)
+ fieldNames[baseName] = count + 1
+ } else {
+ fieldNames[baseName] = 1
+ }
+
+ goField := GoField{
+ Name: field.Name,
+ GoName: finalName,
+ Type: "[]" + structType,
+ IsDynamicArray: true,
+ ArraySizeVariable: field.ArraySizeVariable,
+ ArrayElements: arrayElements,
+ IfVarSet: field.IfVarSet,
+ IfVarNotSet: field.IfVarNotSet,
+ }
+
+ // Generate struct tag
+ tag := fmt.Sprintf("`eq2:\"%s", field.Name)
+ if field.ArraySizeVariable != "" {
+ tag += fmt.Sprintf(",sizeVar:%s", field.ArraySizeVariable)
+ }
+ if field.IfVarSet != "" {
+ tag += fmt.Sprintf(",ifSet:%s", field.IfVarSet)
+ }
+ tag += "\"`"
+ goField.Tag = tag
+
+ goStruct.Fields = append(goStruct.Fields, goField)
+ } else {
+ // Simple array (shouldn't happen but handle it)
+ log.Printf("Warning: array field %s has no children", field.Name)
+ }
+ } else if field.Type == "equipmentItem" {
+ // Handle equipment item arrays
+ // Check for duplicate field names and make unique if needed
+ baseName := toGoName(field.Name)
+ finalName := baseName
+ if count, exists := fieldNames[baseName]; exists {
+ finalName = fmt.Sprintf("%s_%d", baseName, count+1)
+ fieldNames[baseName] = count + 1
+ } else {
+ fieldNames[baseName] = 1
+ }
+
+ goField := GoField{
+ Name: field.Name,
+ GoName: finalName,
+ Type: fmt.Sprintf("[%d]types.EquipmentItem", field.Size),
+ IsArray: true,
+ Size: field.Size,
+ }
+
+ tag := fmt.Sprintf("`eq2:\"%s,size:%d\"`", field.Name, field.Size)
+ goField.Tag = tag
+
+ goStruct.Fields = append(goStruct.Fields, goField)
+ } else {
+ // Regular field
+ goType, _ := mapSimpleType(field.Type)
+ isArray := field.Size > 0
+
+ // Check for duplicate field names and make unique if needed
+ baseName := toGoName(field.Name)
+ finalName := baseName
+ if count, exists := fieldNames[baseName]; exists {
+ finalName = fmt.Sprintf("%s_%d", baseName, count+1)
+ fieldNames[baseName] = count + 1
+ } else {
+ fieldNames[baseName] = 1
+ }
+
+ goField := GoField{
+ Name: field.Name,
+ GoName: finalName,
+ Type: goType,
+ IsArray: isArray,
+ Size: field.Size,
+ IfVarSet: field.IfVarSet,
+ IfVarNotSet: field.IfVarNotSet,
+ }
+
+ if isArray {
+ goField.Type = fmt.Sprintf("[%d]%s", field.Size, goType)
+ }
+
+ // Generate struct tag
+ tag := fmt.Sprintf("`eq2:\"%s", field.Name)
+ if field.Type == "str8" || field.Type == "str16" || field.Type == "str32" ||
+ field.Type == "EQ2_32Bit_String" || field.Type == "EQ2_16Bit_String" || field.Type == "EQ2_8Bit_String" {
+ tag += fmt.Sprintf(",type:%s", field.Type)
+ }
+ if isArray && field.Size > 0 {
+ tag += fmt.Sprintf(",size:%d", field.Size)
+ }
+ if field.IfVarSet != "" {
+ tag += fmt.Sprintf(",ifSet:%s", field.IfVarSet)
+ }
+ tag += "\"`"
+ goField.Tag = tag
+
+ // Add comment if needed
+ if strings.HasPrefix(field.Name, "unknown") || strings.HasPrefix(field.Name, "Unknown") {
+ goField.Comment = " // TODO: Identify purpose"
+ }
+
+ goStruct.Fields = append(goStruct.Fields, goField)
+ }
+ }
+
+ return goStruct
+}
+
+const structTemplate = `// Code generated by codegen. DO NOT EDIT.
+// Source: {{.SourceFile}}
+
+package {{.PackageName}}
+
+import (
+ "encoding/binary"{{if .NeedsMath}}
+ "math"{{end}}
+ "git.sharkk.net/EQ2/Protocol/types"
+)
+
+{{range .Structs}}
+// {{.Name}} represents packet structure for {{if .OpcodeName}}{{.OpcodeName}}{{else}}client version {{.ClientVersion}}{{end}}
+type {{.Name}} struct {
+{{- range .Fields}}
+ {{.GoName}} {{.Type}} {{.Tag}}{{if .Comment}} {{.Comment}}{{end}}
+{{- end}}
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *{{.Name}}) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+ {{range .Fields}}
+ {{- if .IsDynamicArray}}
+ // Write {{.GoName}} array (dynamic size)
+ for _, elem := range p.{{.GoName}} {
+ {{- template "serializeFields" .ArrayElements}}
+ }
+ {{- else if eq .Type "string"}}
+ // Write {{.GoName}} as {{if contains .Tag "str16"}}16-bit{{else if contains .Tag "str32"}}32-bit{{else if contains .Tag "EQ2_32Bit_String"}}32-bit{{else}}8-bit{{end}} length-prefixed string
+ {{- if or (contains .Tag "str16") (contains .Tag "EQ2_16Bit_String")}}
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.{{.GoName}})))
+ offset += 2
+ {{- else if or (contains .Tag "str32") (contains .Tag "EQ2_32Bit_String")}}
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(len(p.{{.GoName}})))
+ offset += 4
+ {{- else}}
+ dest[offset] = byte(len(p.{{.GoName}}))
+ offset++
+ {{- end}}
+ copy(dest[offset:], []byte(p.{{.GoName}}))
+ offset += uint32(len(p.{{.GoName}}))
+ {{- else if .IsArray}}
+ // Write {{.GoName}} array
+ for i := 0; i < {{.Size}}; i++ {
+ {{- if eq (baseType .Type) "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.{{.GoName}}[i]))
+ offset += 4
+ {{- else if eq (baseType .Type) "float64"}}
+ binary.LittleEndian.PutUint64(dest[offset:], math.Float64bits(p.{{.GoName}}[i]))
+ offset += 8
+ {{- else if (eq (baseType .Type) "int8")}}
+ dest[offset] = byte(p.{{.GoName}}[i])
+ offset++
+ {{- else if or (eq (baseType .Type) "uint8") (eq (baseType .Type) "byte")}}
+ dest[offset] = p.{{.GoName}}[i]
+ offset++
+ {{- else if or (eq (baseType .Type) "int16") (eq (baseType .Type) "uint16")}}
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.{{.GoName}}[i]))
+ offset += 2
+ {{- else if or (eq (baseType .Type) "int32") (eq (baseType .Type) "uint32")}}
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.{{.GoName}}[i]))
+ offset += 4
+ {{- else if or (eq (baseType .Type) "int64") (eq (baseType .Type) "uint64")}}
+ binary.LittleEndian.PutUint64(dest[offset:], uint64(p.{{.GoName}}[i]))
+ offset += 8
+ {{- else if eq (baseType .Type) "types.EquipmentItem"}}
+ binary.LittleEndian.PutUint16(dest[offset:], p.{{.GoName}}[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.{{.GoName}}[i].Color.ToUint32())
+ offset += 4
+ {{- end}}
+ }
+ {{- else}}
+ // Write {{.GoName}}
+ {{- if eq .Type "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.{{.GoName}}))
+ offset += 4
+ {{- else if eq .Type "float64"}}
+ binary.LittleEndian.PutUint64(dest[offset:], math.Float64bits(p.{{.GoName}}))
+ offset += 8
+ {{- else if or (eq .Type "int8") (eq .Type "uint8") (eq .Type "byte")}}
+ dest[offset] = byte(p.{{.GoName}})
+ offset++
+ {{- else if or (eq .Type "int16") (eq .Type "uint16")}}
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.{{.GoName}}))
+ offset += 2
+ {{- else if eq .Type "types.Color"}}
+ binary.LittleEndian.PutUint32(dest[offset:], p.{{.GoName}}.ToUint32())
+ offset += 4
+ {{- else if or (eq .Type "int32") (eq .Type "uint32")}}
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.{{.GoName}}))
+ offset += 4
+ {{- else if or (eq .Type "int64") (eq .Type "uint64")}}
+ binary.LittleEndian.PutUint64(dest[offset:], uint64(p.{{.GoName}}))
+ offset += 8
+ {{- end}}
+ {{- end}}
+ {{end}}
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *{{.Name}}) Size() uint32 {
+ size := uint32(0)
+ {{range .Fields}}
+ {{- if .IsDynamicArray}}
+ // Dynamic array: {{.GoName}}
+ for _, elem := range p.{{.GoName}} {
+ {{- template "sizeFields" .ArrayElements}}
+ }
+ {{- else if eq .Type "string"}}
+ {{- if or (contains .Tag "str16") (contains .Tag "EQ2_16Bit_String")}}
+ size += 2 + uint32(len(p.{{.GoName}}))
+ {{- else if or (contains .Tag "str32") (contains .Tag "EQ2_32Bit_String")}}
+ size += 4 + uint32(len(p.{{.GoName}}))
+ {{- else}}
+ size += 1 + uint32(len(p.{{.GoName}}))
+ {{- end}}
+ {{- else if .IsArray}}
+ {{- if eq (baseType .Type) "types.EquipmentItem"}}
+ size += {{.Size}} * 6
+ {{- else if eq (sizeOf (baseType .Type)) 1}}
+ size += {{.Size}}
+ {{- else}}
+ size += {{.Size}} * {{sizeOf (baseType .Type)}}
+ {{- end}}
+ {{- else}}
+ size += {{sizeOf .Type}}
+ {{- end}}
+ {{end}}
+ return size
+}
+{{end}}
+
+{{define "serializeFields"}}
+{{- range .}}
+{{- if .IsDynamicArray}}
+ // Write nested {{.GoName}} array
+ for _, nestedElem := range elem.{{.GoName}} {
+ {{- template "serializeNestedFields" .ArrayElements}}
+ }
+{{- else if eq .Type "string"}}
+ // Write {{.GoName}} string field
+ dest[offset] = byte(len(elem.{{.GoName}}))
+ offset++
+ copy(dest[offset:], []byte(elem.{{.GoName}}))
+ offset += uint32(len(elem.{{.GoName}}))
+{{- else if .IsArray}}
+ // Write {{.GoName}} array field
+ for i := 0; i < {{.Size}}; i++ {
+ {{- if eq (baseType .Type) "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(elem.{{.GoName}}[i]))
+ offset += 4
+ {{- else if eq (baseType .Type) "uint32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], elem.{{.GoName}}[i])
+ offset += 4
+ {{- else if eq (baseType .Type) "uint16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], elem.{{.GoName}}[i])
+ offset += 2
+ {{- else}}
+ dest[offset] = byte(elem.{{.GoName}}[i])
+ offset++
+ {{- end}}
+ }
+{{- else if eq .Type "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(elem.{{.GoName}}))
+ offset += 4
+{{- else if eq .Type "types.Color"}}
+ binary.LittleEndian.PutUint32(dest[offset:], elem.{{.GoName}}.ToUint32())
+ offset += 4
+{{- else if eq .Type "uint32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], elem.{{.GoName}})
+ offset += 4
+{{- else if eq .Type "int32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(elem.{{.GoName}}))
+ offset += 4
+{{- else if eq .Type "uint16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], elem.{{.GoName}})
+ offset += 2
+{{- else if eq .Type "int16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(elem.{{.GoName}}))
+ offset += 2
+{{- else if eq .Type "int8"}}
+ dest[offset] = byte(elem.{{.GoName}})
+ offset++
+{{- else if eq .Type "uint8"}}
+ dest[offset] = elem.{{.GoName}}
+ offset++
+{{- else}}
+ dest[offset] = byte(elem.{{.GoName}})
+ offset++
+{{- end}}
+{{- end}}
+{{end}}
+
+{{define "sizeFields"}}
+ _ = elem // Avoid unused variable warning
+{{- range .}}
+{{- if .IsDynamicArray}}
+ // Nested array: {{.GoName}}
+ for _, nestedElem := range elem.{{.GoName}} {
+ {{- template "sizeNestedFields" .ArrayElements}}
+ }
+{{- else if eq .Type "string"}}
+ size += 1 + uint32(len(elem.{{.GoName}}))
+{{- else if .IsArray}}
+ {{- if eq (sizeOf (baseType .Type)) 1}}
+ size += {{.Size}}
+ {{- else}}
+ size += {{.Size}} * {{sizeOf (baseType .Type)}}
+ {{- end}}
+{{- else}}
+ size += {{sizeOf .Type}}
+{{- end}}
+{{- end}}
+{{end}}
+
+{{define "serializeNestedFields"}}
+{{- range .}}
+{{- if .IsDynamicArray}}
+ // Write deeply nested {{.GoName}} array
+ for _, deepNested := range nestedElem.{{.GoName}} {
+ // TODO: Handle deeper nesting if needed
+ _ = deepNested
+ }
+{{- else if eq .Type "string"}}
+ // Write {{.GoName}} string field
+ dest[offset] = byte(len(nestedElem.{{.GoName}}))
+ offset++
+ copy(dest[offset:], []byte(nestedElem.{{.GoName}}))
+ offset += uint32(len(nestedElem.{{.GoName}}))
+{{- else if .IsArray}}
+ // Write {{.GoName}} array field
+ for i := 0; i < {{.Size}}; i++ {
+ {{- if eq (baseType .Type) "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(nestedElem.{{.GoName}}[i]))
+ offset += 4
+ {{- else if eq (baseType .Type) "uint32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.{{.GoName}}[i])
+ offset += 4
+ {{- else if eq (baseType .Type) "uint16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.{{.GoName}}[i])
+ offset += 2
+ {{- else}}
+ dest[offset] = nestedElem.{{.GoName}}[i]
+ offset++
+ {{- end}}
+ }
+{{- else if eq .Type "float32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(nestedElem.{{.GoName}}))
+ offset += 4
+{{- else if eq .Type "types.Color"}}
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.{{.GoName}}.ToUint32())
+ offset += 4
+{{- else if eq .Type "uint32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.{{.GoName}})
+ offset += 4
+{{- else if eq .Type "int32"}}
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(nestedElem.{{.GoName}}))
+ offset += 4
+{{- else if eq .Type "uint16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.{{.GoName}})
+ offset += 2
+{{- else if eq .Type "int16"}}
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(nestedElem.{{.GoName}}))
+ offset += 2
+{{- else if eq .Type "int8"}}
+ dest[offset] = byte(nestedElem.{{.GoName}})
+ offset++
+{{- else if eq .Type "uint8"}}
+ dest[offset] = nestedElem.{{.GoName}}
+ offset++
+{{- else}}
+ dest[offset] = byte(nestedElem.{{.GoName}})
+ offset++
+{{- end}}
+{{- end}}
+{{end}}
+
+{{define "sizeNestedFields"}}
+ _ = nestedElem // Avoid unused variable
+{{- range .}}
+{{- if .IsDynamicArray}}
+ // Deeply nested array: {{.GoName}}
+ for _, deepNested := range nestedElem.{{.GoName}} {
+ // TODO: Handle deeper nesting if needed
+ _ = deepNested
+ }
+{{- else if eq .Type "string"}}
+ size += 1 + uint32(len(nestedElem.{{.GoName}}))
+{{- else if .IsArray}}
+ {{- if eq (sizeOf (baseType .Type)) 1}}
+ size += {{.Size}}
+ {{- else}}
+ size += {{.Size}} * {{sizeOf (baseType .Type)}}
+ {{- end}}
+{{- else}}
+ size += {{sizeOf .Type}}
+{{- end}}
+{{- end}}
+{{end}}
+`
+
+func contains(s, substr string) bool {
+ return strings.Contains(s, substr)
+}
+
+func baseType(arrayType string) string {
+ // Extract base type from array declaration like "[10]uint32"
+ if strings.HasPrefix(arrayType, "[") {
+ idx := strings.Index(arrayType, "]")
+ if idx > 0 {
+ return arrayType[idx+1:]
+ }
+ }
+ return arrayType
+}
+
+func sizeOf(typeName string) int {
+ // Return the size in bytes for a given type
+ switch typeName {
+ case "int8", "uint8", "byte":
+ return 1
+ case "int16", "uint16":
+ return 2
+ case "int32", "uint32", "float32", "types.Color":
+ return 4
+ case "int64", "uint64", "float64":
+ return 8
+ case "types.EquipmentItem":
+ return 6
+ default:
+ return 0
+ }
+}
+
+func main() {
+ var (
+ input = flag.String("input", "", "Input XML file or directory")
+ output = flag.String("output", "", "Output Go file or directory")
+ pkgName = flag.String("package", "generated", "Package name for generated code")
+ )
+ flag.Parse()
+
+ if *input == "" || *output == "" {
+ fmt.Fprintf(os.Stderr, "Usage: %s -input -output [-package ]\n", os.Args[0])
+ os.Exit(1)
+ }
+
+ // Get file info
+ info, err := os.Stat(*input)
+ if err != nil {
+ log.Fatalf("Error accessing input: %v", err)
+ }
+
+ if info.IsDir() {
+ // Process directory
+ files, err := filepath.Glob(filepath.Join(*input, "*.xml"))
+ if err != nil {
+ log.Fatalf("Error listing XML files: %v", err)
+ }
+
+ for _, xmlFile := range files {
+ processFile(xmlFile, *output, *pkgName)
+ }
+ } else {
+ // Process single file
+ processFile(*input, *output, *pkgName)
+ }
+}
+
+func processFile(inputFile, outputPath, packageName string) {
+ log.Printf("Processing %s...", inputFile)
+
+ // Parse XML file
+ structs, err := parseXMLFile(inputFile)
+ if err != nil {
+ log.Printf("Error parsing %s: %v", inputFile, err)
+ return
+ }
+
+ // Convert to Go structs
+ goStructs := make([]GoStruct, 0, len(structs))
+
+ for _, xmlStruct := range structs {
+ goStructs = append(goStructs, convertToGoStruct(xmlStruct, packageName))
+ }
+
+ // Determine output file
+ outputFile := outputPath
+ if info, err := os.Stat(outputPath); err == nil && info.IsDir() {
+ base := strings.TrimSuffix(filepath.Base(inputFile), ".xml")
+ outputFile = filepath.Join(outputPath, base+".go")
+ }
+
+ // Generate code
+ tmpl := template.New("struct")
+ tmpl.Funcs(template.FuncMap{
+ "contains": contains,
+ "baseType": baseType,
+ "sizeOf": sizeOf,
+ })
+
+ // Parse the main template
+ tmpl, err = tmpl.Parse(structTemplate)
+ if err != nil {
+ log.Fatalf("Error parsing template: %v", err)
+ }
+
+ // Create output file
+ out, err := os.Create(outputFile)
+ if err != nil {
+ log.Fatalf("Error creating output file: %v", err)
+ }
+ defer out.Close()
+
+ // Check if math package is needed (for float types)
+ needsMath := false
+ for _, goStruct := range goStructs {
+ for _, field := range goStruct.Fields {
+ if strings.Contains(field.Type, "float") {
+ needsMath = true
+ break
+ }
+ }
+ if needsMath {
+ break
+ }
+ }
+
+ // Execute template
+ data := GenerateOutput{
+ SourceFile: filepath.Base(inputFile),
+ PackageName: packageName,
+ Structs: goStructs,
+ NeedsMath: needsMath,
+ }
+
+ if err := tmpl.Execute(out, data); err != nil {
+ log.Fatalf("Error executing template: %v", err)
+ }
+
+ log.Printf("Generated %s", outputFile)
+}
diff --git a/defs/generated/common.go b/defs/generated/common.go
new file mode 100644
index 0000000..a40329e
--- /dev/null
+++ b/defs/generated/common.go
@@ -0,0 +1,5941 @@
+// Code generated by codegen. DO NOT EDIT.
+// Source: common.xml
+
+package generated
+
+import (
+ "encoding/binary"
+ "math"
+ "git.sharkk.net/EQ2/Protocol/types"
+)
+
+
+// CreateCharacter represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacter struct {
+ AccountId uint32 `eq2:"account_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Unknown1 [2]uint8 `eq2:"unknown1,size:2"` // TODO: Identify purpose
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor [3]float32 `eq2:"skin_color,size:3"`
+ EyeColor [3]float32 `eq2:"eye_color,size:3"`
+ HairColor1 [3]float32 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]float32 `eq2:"hair_color2,size:3"`
+ HairHighlight [3]float32 `eq2:"hair_highlight,size:3"`
+ Unknown2 [26]uint8 `eq2:"unknown2,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor [3]float32 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]float32 `eq2:"hair_type_highlight_color,size:3"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor [3]float32 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]float32 `eq2:"hair_face_highlight_color,size:3"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor [3]float32 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]float32 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor [3]float32 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]float32 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]float32 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacter) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Unknown1 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown1[i]
+ offset++
+ }
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SkinColor[i]))
+ offset += 4
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeColor[i]))
+ offset += 4
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor1[i]))
+ offset += 4
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor2[i]))
+ offset += 4
+ }
+
+ // Write HairHighlight array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairHighlight[i]))
+ offset += 4
+ }
+
+ // Write Unknown2 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeColor[i]))
+ offset += 4
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceColor[i]))
+ offset += 4
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.ShirtColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownChestColor[i]))
+ offset += 4
+ }
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.PantsColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownLegsColor[i]))
+ offset += 4
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Unknown9[i]))
+ offset += 4
+ }
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacter) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV373 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV373 struct {
+ Unknown0 uint32 `eq2:"unknown0"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Unknown1 [2]uint8 `eq2:"unknown1,size:2"` // TODO: Identify purpose
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor [3]float32 `eq2:"skin_color,size:3"`
+ EyeColor [3]float32 `eq2:"eye_color,size:3"`
+ HairColor1 [3]float32 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]float32 `eq2:"hair_color2,size:3"`
+ HairHighlight [3]float32 `eq2:"hair_highlight,size:3"`
+ Unknown2 [26]uint8 `eq2:"unknown2,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor [3]float32 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]float32 `eq2:"hair_type_highlight_color,size:3"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor [3]float32 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]float32 `eq2:"hair_face_highlight_color,size:3"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor [3]float32 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]float32 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor [3]float32 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]float32 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]float32 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV373) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown0))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Unknown1 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown1[i]
+ offset++
+ }
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SkinColor[i]))
+ offset += 4
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeColor[i]))
+ offset += 4
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor1[i]))
+ offset += 4
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor2[i]))
+ offset += 4
+ }
+
+ // Write HairHighlight array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairHighlight[i]))
+ offset += 4
+ }
+
+ // Write Unknown2 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeColor[i]))
+ offset += 4
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceColor[i]))
+ offset += 4
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.ShirtColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownChestColor[i]))
+ offset += 4
+ }
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.PantsColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownLegsColor[i]))
+ offset += 4
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Unknown9[i]))
+ offset += 4
+ }
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV373) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV546 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV546 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ CcUnknown0 uint8 `eq2:"cc_unknown_0"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor [3]float32 `eq2:"skin_color,size:3"`
+ EyeColor [3]float32 `eq2:"eye_color,size:3"`
+ HairColor1 [3]float32 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]float32 `eq2:"hair_color2,size:3"`
+ HairHighlight [3]float32 `eq2:"hair_highlight,size:3"`
+ Unknown2 [26]uint8 `eq2:"unknown2,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor [3]float32 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]float32 `eq2:"hair_type_highlight_color,size:3"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor [3]float32 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]float32 `eq2:"hair_face_highlight_color,size:3"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor [3]float32 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]float32 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor [3]float32 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]float32 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]float32 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV546) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write CcUnknown0
+ dest[offset] = byte(p.CcUnknown0)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SkinColor[i]))
+ offset += 4
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeColor[i]))
+ offset += 4
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor1[i]))
+ offset += 4
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor2[i]))
+ offset += 4
+ }
+
+ // Write HairHighlight array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairHighlight[i]))
+ offset += 4
+ }
+
+ // Write Unknown2 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeColor[i]))
+ offset += 4
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceColor[i]))
+ offset += 4
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.ShirtColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownChestColor[i]))
+ offset += 4
+ }
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.PantsColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownLegsColor[i]))
+ offset += 4
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Unknown9[i]))
+ offset += 4
+ }
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV546) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV561 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV561 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor [3]float32 `eq2:"skin_color,size:3"`
+ EyeColor [3]float32 `eq2:"eye_color,size:3"`
+ HairColor1 [3]float32 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]float32 `eq2:"hair_color2,size:3"`
+ HairHighlight [3]float32 `eq2:"hair_highlight,size:3"`
+ Unknown2 [26]uint8 `eq2:"unknown2,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor [3]float32 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]float32 `eq2:"hair_type_highlight_color,size:3"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor [3]float32 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]float32 `eq2:"hair_face_highlight_color,size:3"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor [3]float32 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]float32 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor [3]float32 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]float32 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]float32 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV561) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SkinColor[i]))
+ offset += 4
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeColor[i]))
+ offset += 4
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor1[i]))
+ offset += 4
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairColor2[i]))
+ offset += 4
+ }
+
+ // Write HairHighlight array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairHighlight[i]))
+ offset += 4
+ }
+
+ // Write Unknown2 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeColor[i]))
+ offset += 4
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairTypeHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceColor[i]))
+ offset += 4
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.HairFaceHighlightColor[i]))
+ offset += 4
+ }
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.ShirtColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownChestColor[i]))
+ offset += 4
+ }
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.PantsColor[i]))
+ offset += 4
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.UnknownLegsColor[i]))
+ offset += 4
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Unknown9[i]))
+ offset += 4
+ }
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV561) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV562 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV562 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ SkinColor2 types.Color `eq2:"skin_color2"`
+ EyeColor types.Color `eq2:"eye_color"`
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown8 [26]uint8 `eq2:"unknown8,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknown11 [26]uint8 `eq2:"soga_unknown11,size:26"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV562) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write SkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor2.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV562) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV869 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV869 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ SkinColor2 types.Color `eq2:"skin_color2"`
+ EyeColor types.Color `eq2:"eye_color"`
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ HairHighlight types.Color `eq2:"hair_highlight"`
+ Unknown8 [26]uint8 `eq2:"unknown8,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknownColor1 types.Color `eq2:"soga_unknown_color1"`
+ SogaUnknown11 [26]uint8 `eq2:"soga_unknown11,size:26"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV869) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write SkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor2.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write HairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairHighlight.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownColor1.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV869) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV1096 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV1096 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ SkinColor2 types.Color `eq2:"skin_color2"`
+ EyeColor types.Color `eq2:"eye_color"`
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ HairHighlight types.Color `eq2:"hair_highlight"`
+ Unknown8 [26]uint8 `eq2:"unknown8,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknownColor types.Color `eq2:"soga_unknown_color"`
+ SogaUnknown11 [26]uint8 `eq2:"soga_unknown11,size:26"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV1096) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write SkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor2.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write HairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairHighlight.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV1096) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV57080 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV57080 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ Unknown10 uint16 `eq2:"unknown10"` // TODO: Identify purpose
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ EyeColor types.Color `eq2:"eye_color"`
+ UnknownSkinColor2 types.Color `eq2:"unknown_skin_color2"` // TODO: Identify purpose
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ HairHighlight types.Color `eq2:"hair_highlight"`
+ Unknown8 [26]uint8 `eq2:"unknown8,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknownColor types.Color `eq2:"soga_unknown_color"`
+ SogaUnknown11 [26]uint8 `eq2:"soga_unknown11,size:26"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV57080) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write Unknown10
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown10))
+ offset += 2
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write UnknownSkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownSkinColor2.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write HairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairHighlight.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV57080) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV60085 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV60085 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint8 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ Unknown10 uint16 `eq2:"unknown10"` // TODO: Identify purpose
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ EyeColor types.Color `eq2:"eye_color"`
+ UnknownSkinColor2 types.Color `eq2:"unknown_skin_color2"` // TODO: Identify purpose
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ HairHighlight types.Color `eq2:"hair_highlight"`
+ Unknown8 [26]uint8 `eq2:"unknown8,size:26"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknownColor types.Color `eq2:"soga_unknown_color"`
+ SogaUnknown11 [26]uint8 `eq2:"soga_unknown11,size:26"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV60085) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ dest[offset] = byte(p.StartingZone)
+ offset++
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write Unknown10
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown10))
+ offset += 2
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write UnknownSkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownSkinColor2.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write HairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairHighlight.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 26; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV60085) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 26
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CreateCharacterV64659 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV64659 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint32 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ SkinColor2 types.Color `eq2:"skin_color2"`
+ EyeColor types.Color `eq2:"eye_color"`
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown8 [38]uint8 `eq2:"unknown8,size:38"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknown11 [38]uint8 `eq2:"soga_unknown11,size:38"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+ Unknown13 [2]uint8 `eq2:"unknown13,size:2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV64659) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.StartingZone))
+ offset += 4
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write SkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor2.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 38; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 38; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ // Write Unknown13 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown13[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV64659) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 38
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 38
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ return size
+}
+
+// CreateCharacterV65534 represents packet structure for OP_CreateCharacterRequestMsg
+type CreateCharacterV65534 struct {
+ Unknown0 uint8 `eq2:"unknown0"` // TODO: Identify purpose
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 uint8 `eq2:"unknown3"` // TODO: Identify purpose
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Gender uint8 `eq2:"gender"`
+ Deity uint8 `eq2:"deity"`
+ Class uint8 `eq2:"class"`
+ Level uint8 `eq2:"level"`
+ StartingZone uint32 `eq2:"starting_zone"`
+ Version uint8 `eq2:"version"`
+ RaceFile string `eq2:"race_file,type:str16"`
+ SkinColor types.Color `eq2:"skin_color"`
+ SkinColor2 types.Color `eq2:"skin_color2"`
+ EyeColor types.Color `eq2:"eye_color"`
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown8 [38]uint8 `eq2:"unknown8,size:38"` // TODO: Identify purpose
+ HairFile string `eq2:"hair_file,type:str16"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ FaceFile string `eq2:"face_file,type:str16"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingFile string `eq2:"wing_file,type:str16"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestFile string `eq2:"chest_file,type:str16"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsFile string `eq2:"legs_file,type:str16"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ Eyes2 [3]float32 `eq2:"eyes2,size:3"`
+ Ears [3]float32 `eq2:"ears,size:3"`
+ EyeBrows [3]float32 `eq2:"eye_brows,size:3"`
+ Cheeks [3]float32 `eq2:"cheeks,size:3"`
+ Lips [3]float32 `eq2:"lips,size:3"`
+ Chin [3]float32 `eq2:"chin,size:3"`
+ Nose [3]float32 `eq2:"nose,size:3"`
+ BodySize float32 `eq2:"body_size"`
+ BodyAge float32 `eq2:"body_age"`
+ SogaVersion uint8 `eq2:"soga_version"`
+ SogaRaceFile string `eq2:"soga_race_file,type:str16"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairHighlight types.Color `eq2:"soga_hair_highlight"`
+ SogaUnknown11 [38]uint8 `eq2:"soga_unknown11,size:38"`
+ SogaHairFile string `eq2:"soga_hair_file,type:str16"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaFaceFile string `eq2:"soga_face_file,type:str16"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ SogaWingFile string `eq2:"soga_wing_file,type:str16"`
+ SogaWingColor1 types.Color `eq2:"soga_wing_color1"`
+ SogaWingColor2 types.Color `eq2:"soga_wing_color2"`
+ SogaChestFile string `eq2:"soga_chest_file,type:str16"`
+ SogaShirtColor types.Color `eq2:"soga_shirt_color"`
+ SogaUnknownChestColor types.Color `eq2:"soga_unknown_chest_color"`
+ SogaLegsFile string `eq2:"soga_legs_file,type:str16"`
+ SogaPantsColor types.Color `eq2:"soga_pants_color"`
+ SogaUnknownLegsColor types.Color `eq2:"soga_unknown_legs_color"`
+ SogaUnknown12 types.Color `eq2:"soga_unknown12"`
+ SogaEyes2 [3]float32 `eq2:"soga_eyes2,size:3"`
+ SogaEars [3]float32 `eq2:"soga_ears,size:3"`
+ SogaEyeBrows [3]float32 `eq2:"soga_eye_brows,size:3"`
+ SogaCheeks [3]float32 `eq2:"soga_cheeks,size:3"`
+ SogaLips [3]float32 `eq2:"soga_lips,size:3"`
+ SogaChin [3]float32 `eq2:"soga_chin,size:3"`
+ SogaNose [3]float32 `eq2:"soga_nose,size:3"`
+ SogaBodySize float32 `eq2:"soga_body_size"`
+ SogaBodyAge float32 `eq2:"soga_body_age"`
+ Unknown13 [2]uint8 `eq2:"unknown13,size:2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CreateCharacterV65534) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Unknown0
+ dest[offset] = byte(p.Unknown0)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3
+ dest[offset] = byte(p.Unknown3)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Deity
+ dest[offset] = byte(p.Deity)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ dest[offset] = byte(p.Level)
+ offset++
+
+ // Write StartingZone
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.StartingZone))
+ offset += 4
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.RaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.RaceFile))
+ offset += uint32(len(p.RaceFile))
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write SkinColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor2.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 38; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write HairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.HairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.HairFile))
+ offset += uint32(len(p.HairFile))
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write FaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.FaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.FaceFile))
+ offset += uint32(len(p.FaceFile))
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WingFile))
+ offset += uint32(len(p.WingFile))
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ChestFile))
+ offset += uint32(len(p.ChestFile))
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.LegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.LegsFile))
+ offset += uint32(len(p.LegsFile))
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write Eyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Eyes2[i]))
+ offset += 4
+ }
+
+ // Write Ears array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Ears[i]))
+ offset += 4
+ }
+
+ // Write EyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.EyeBrows[i]))
+ offset += 4
+ }
+
+ // Write Cheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Cheeks[i]))
+ offset += 4
+ }
+
+ // Write Lips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Lips[i]))
+ offset += 4
+ }
+
+ // Write Chin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Chin[i]))
+ offset += 4
+ }
+
+ // Write Nose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.Nose[i]))
+ offset += 4
+ }
+
+ // Write BodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodySize))
+ offset += 4
+
+ // Write BodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.BodyAge))
+ offset += 4
+
+ // Write SogaVersion
+ dest[offset] = byte(p.SogaVersion)
+ offset++
+
+ // Write SogaRaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaRaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaRaceFile))
+ offset += uint32(len(p.SogaRaceFile))
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairHighlight
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairHighlight.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown11 array
+ for i := 0; i < 38; i++ {
+ dest[offset] = p.SogaUnknown11[i]
+ offset++
+ }
+
+ // Write SogaHairFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaHairFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaHairFile))
+ offset += uint32(len(p.SogaHairFile))
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaFaceFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaFaceFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaFaceFile))
+ offset += uint32(len(p.SogaFaceFile))
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaWingFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaWingFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaWingFile))
+ offset += uint32(len(p.SogaWingFile))
+
+ // Write SogaWingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor1.ToUint32())
+ offset += 4
+
+ // Write SogaWingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaWingColor2.ToUint32())
+ offset += 4
+
+ // Write SogaChestFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaChestFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaChestFile))
+ offset += uint32(len(p.SogaChestFile))
+
+ // Write SogaShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaShirtColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write SogaLegsFile as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SogaLegsFile)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SogaLegsFile))
+ offset += uint32(len(p.SogaLegsFile))
+
+ // Write SogaPantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaPantsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write SogaUnknown12
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaUnknown12.ToUint32())
+ offset += 4
+
+ // Write SogaEyes2 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyes2[i]))
+ offset += 4
+ }
+
+ // Write SogaEars array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEars[i]))
+ offset += 4
+ }
+
+ // Write SogaEyeBrows array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaEyeBrows[i]))
+ offset += 4
+ }
+
+ // Write SogaCheeks array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaCheeks[i]))
+ offset += 4
+ }
+
+ // Write SogaLips array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaLips[i]))
+ offset += 4
+ }
+
+ // Write SogaChin array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaChin[i]))
+ offset += 4
+ }
+
+ // Write SogaNose array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaNose[i]))
+ offset += 4
+ }
+
+ // Write SogaBodySize
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodySize))
+ offset += 4
+
+ // Write SogaBodyAge
+ binary.LittleEndian.PutUint32(dest[offset:], math.Float32bits(p.SogaBodyAge))
+ offset += 4
+
+ // Write Unknown13 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown13[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CreateCharacterV65534) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.RaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 38
+
+ size += 2 + uint32(len(p.HairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.FaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.WingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.ChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.LegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.SogaRaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 38
+
+ size += 2 + uint32(len(p.SogaHairFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaFaceFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaWingFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaChestFile))
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.SogaLegsFile))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 3 * 4
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ return size
+}
+
+// BadLanguageFilter represents packet structure for OP_BadLanguageFilter
+type BadLanguageFilter struct {
+ NumWords uint16 `eq2:"num_words"`
+ WordsArray []struct {
+ Word string `eq2:"word,type:str16"`
+ } `eq2:"words_array,sizeVar:num_words"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *BadLanguageFilter) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWords
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.NumWords))
+ offset += 2
+
+ // Write WordsArray array (dynamic size)
+ for _, elem := range p.WordsArray {
+ // Write Word string field
+ dest[offset] = byte(len(elem.Word))
+ offset++
+ copy(dest[offset:], []byte(elem.Word))
+ offset += uint32(len(elem.Word))
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *BadLanguageFilter) Size() uint32 {
+ size := uint32(0)
+
+ size += 2
+
+ // Dynamic array: WordsArray
+ for _, elem := range p.WordsArray {
+ _ = elem // Avoid unused variable warning
+ size += 1 + uint32(len(elem.Word))
+
+ }
+
+ return size
+}
+
+
+
+
+
+
+
+
+
diff --git a/defs/generated/login.go b/defs/generated/login.go
new file mode 100644
index 0000000..8c68607
--- /dev/null
+++ b/defs/generated/login.go
@@ -0,0 +1,7722 @@
+// Code generated by codegen. DO NOT EDIT.
+// Source: login.xml
+
+package generated
+
+import (
+ "encoding/binary"
+ "git.sharkk.net/EQ2/Protocol/types"
+)
+
+
+// LSCreateCharacterReply represents packet structure for OP_CreateCharacterReplyMsg
+type LSCreateCharacterReply struct {
+ AccountId uint32 `eq2:"account_id"`
+ Response uint8 `eq2:"response"`
+ Name string `eq2:"name,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSCreateCharacterReply) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSCreateCharacterReply) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.Name))
+
+ return size
+}
+
+// LSCreateCharacterReplyV1189 represents packet structure for OP_CreateCharacterReplyMsg
+type LSCreateCharacterReplyV1189 struct {
+ AccountId uint32 `eq2:"account_id"`
+ Unknown uint32 `eq2:"unknown"` // TODO: Identify purpose
+ Response uint8 `eq2:"response"`
+ Name string `eq2:"name,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSCreateCharacterReplyV1189) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown))
+ offset += 4
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSCreateCharacterReplyV1189) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.Name))
+
+ return size
+}
+
+// LSCreateCharacterReplyV60085 represents packet structure for OP_CreateCharacterReplyMsg
+type LSCreateCharacterReplyV60085 struct {
+ AccountId uint32 `eq2:"account_id"`
+ Unknown uint32 `eq2:"unknown"` // TODO: Identify purpose
+ Response uint8 `eq2:"response"`
+ Name string `eq2:"name,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSCreateCharacterReplyV60085) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown))
+ offset += 4
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSCreateCharacterReplyV60085) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 2 + uint32(len(p.Name))
+
+ return size
+}
+
+// LSDeleteCharacterRequest represents packet structure for OP_DeleteCharacterRequestMsg
+type LSDeleteCharacterRequest struct {
+ CharId uint32 `eq2:"char_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Unknown uint32 `eq2:"unknown"` // TODO: Identify purpose
+ Name string `eq2:"name,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSDeleteCharacterRequest) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write CharId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CharId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Unknown
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSDeleteCharacterRequest) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ return size
+}
+
+// LSDeleteCharacterResponse represents packet structure for OP_DeleteCharacterReplyMsg
+type LSDeleteCharacterResponse struct {
+ Response uint8 `eq2:"response"`
+ ServerId uint32 `eq2:"server_id"`
+ CharId uint32 `eq2:"char_id"`
+ AccountId uint32 `eq2:"account_id"`
+ Name string `eq2:"name,type:str16"`
+ MaxCharacters uint32 `eq2:"max_characters"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSDeleteCharacterResponse) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write CharId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CharId))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write MaxCharacters
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.MaxCharacters))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSDeleteCharacterResponse) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 4
+
+ return size
+}
+
+// LSLoginRequest represents packet structure for OP_LoginRequestMsg
+type LSLoginRequest struct {
+ SessionID string `eq2:"sessionID,type:str16"`
+ SessionRecycleToken string `eq2:"sessionRecycleToken,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Password string `eq2:"password,type:str16"`
+ AcctNum uint32 `eq2:"acctNum"`
+ PassCode uint32 `eq2:"passCode"`
+ Version uint16 `eq2:"version"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginRequest) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write SessionID as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SessionID)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SessionID))
+ offset += uint32(len(p.SessionID))
+
+ // Write SessionRecycleToken as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.SessionRecycleToken)))
+ offset += 2
+ copy(dest[offset:], []byte(p.SessionRecycleToken))
+ offset += uint32(len(p.SessionRecycleToken))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write AcctNum
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AcctNum))
+ offset += 4
+
+ // Write PassCode
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.PassCode))
+ offset += 4
+
+ // Write Version
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Version))
+ offset += 2
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginRequest) Size() uint32 {
+ size := uint32(0)
+
+ size += 2 + uint32(len(p.SessionID))
+
+ size += 2 + uint32(len(p.SessionRecycleToken))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ return size
+}
+
+// LSLoginRequestV562 represents packet structure for OP_LoginRequestMsg
+type LSLoginRequestV562 struct {
+ Accesscode string `eq2:"accesscode,type:str16"`
+ Unknown1 string `eq2:"unknown1,type:str16"` // TODO: Identify purpose
+ Username string `eq2:"username,type:str16"`
+ Password string `eq2:"password,type:str16"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ Unknown3 [2]uint8 `eq2:"unknown3,size:2"` // TODO: Identify purpose
+ Version uint32 `eq2:"version"`
+ Unknown4 uint16 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint32 `eq2:"unknown5"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginRequestV562) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Accesscode as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Accesscode)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Accesscode))
+ offset += uint32(len(p.Accesscode))
+
+ // Write Unknown1 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown1)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown1))
+ offset += uint32(len(p.Unknown1))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write Unknown3 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown3[i]
+ offset++
+ }
+
+ // Write Version
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Version))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown4))
+ offset += 2
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginRequestV562) Size() uint32 {
+ size := uint32(0)
+
+ size += 2 + uint32(len(p.Accesscode))
+
+ size += 2 + uint32(len(p.Unknown1))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 8
+
+ size += 2
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ return size
+}
+
+// LSLoginRequestV1208 represents packet structure for OP_LoginRequestMsg
+type LSLoginRequestV1208 struct {
+ Accesscode string `eq2:"accesscode,type:str16"`
+ Unknown1 string `eq2:"unknown1,type:str16"` // TODO: Identify purpose
+ Username string `eq2:"username,type:str16"`
+ Password string `eq2:"password,type:str16"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ Unknown3 [2]uint8 `eq2:"unknown3,size:2"` // TODO: Identify purpose
+ Version uint16 `eq2:"version"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 [3]uint32 `eq2:"unknown5,size:3"` // TODO: Identify purpose
+ Unknown6 uint16 `eq2:"unknown6"` // TODO: Identify purpose
+ Unknown7 string `eq2:"unknown7,type:str16"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginRequestV1208) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Accesscode as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Accesscode)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Accesscode))
+ offset += uint32(len(p.Accesscode))
+
+ // Write Unknown1 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown1)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown1))
+ offset += uint32(len(p.Unknown1))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write Unknown3 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown3[i]
+ offset++
+ }
+
+ // Write Version
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Version))
+ offset += 2
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5[i]))
+ offset += 4
+ }
+
+ // Write Unknown6
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown6))
+ offset += 2
+
+ // Write Unknown7 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown7)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown7))
+ offset += uint32(len(p.Unknown7))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginRequestV1208) Size() uint32 {
+ size := uint32(0)
+
+ size += 2 + uint32(len(p.Accesscode))
+
+ size += 2 + uint32(len(p.Unknown1))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 8
+
+ size += 2
+
+ size += 2
+
+ size += 1
+
+ size += 3 * 4
+
+ size += 2
+
+ size += 2 + uint32(len(p.Unknown7))
+
+ return size
+}
+
+// LSWorldList represents packet structure for OP_WorldListMsg
+type LSWorldList struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Online uint8 `eq2:"online"`
+ Locked uint8 `eq2:"locked"`
+ Unknown2 uint8 `eq2:"unknown2"`
+ Unknown3 uint8 `eq2:"unknown3"`
+ Load uint8 `eq2:"load"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldList) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ dest[offset] = elem.Online
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Unknown2
+ offset++
+ dest[offset] = elem.Unknown3
+ offset++
+ dest[offset] = elem.Load
+ offset++
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldList) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+
+ }
+
+ return size
+}
+
+// LSWorldListV373 represents packet structure for OP_WorldListMsg
+type LSWorldListV373 struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Tag uint8 `eq2:"tag"`
+ Locked uint8 `eq2:"locked"`
+ Hidden uint8 `eq2:"hidden"`
+ Unknown uint8 `eq2:"unknown"`
+ NumPlayers uint16 `eq2:"num_players"`
+ Load uint8 `eq2:"load"`
+ NumberOnlineFlag uint8 `eq2:"number_online_flag"`
+ AllowedRaces uint32 `eq2:"allowed_races"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldListV373) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ dest[offset] = elem.Tag
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Hidden
+ offset++
+ dest[offset] = elem.Unknown
+ offset++
+ binary.LittleEndian.PutUint16(dest[offset:], elem.NumPlayers)
+ offset += 2
+ dest[offset] = elem.Load
+ offset++
+ dest[offset] = elem.NumberOnlineFlag
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], elem.AllowedRaces)
+ offset += 4
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldListV373) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 2
+ size += 1
+ size += 1
+ size += 4
+
+ }
+
+ return size
+}
+
+// LSWorldListV546 represents packet structure for OP_WorldListMsg
+type LSWorldListV546 struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Name2 string `eq2:"name2,type:str16"`
+ Tag uint8 `eq2:"tag"`
+ Locked uint8 `eq2:"locked"`
+ Hidden uint8 `eq2:"hidden"`
+ Unknown uint8 `eq2:"unknown"`
+ NumPlayers uint16 `eq2:"num_players"`
+ Load uint8 `eq2:"load"`
+ NumberOnlineFlag uint8 `eq2:"number_online_flag"`
+ Unknown2 uint8 `eq2:"unknown2"`
+ AllowedRaces uint32 `eq2:"allowed_races"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldListV546) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ // Write Name2 string field
+ dest[offset] = byte(len(elem.Name2))
+ offset++
+ copy(dest[offset:], []byte(elem.Name2))
+ offset += uint32(len(elem.Name2))
+ dest[offset] = elem.Tag
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Hidden
+ offset++
+ dest[offset] = elem.Unknown
+ offset++
+ binary.LittleEndian.PutUint16(dest[offset:], elem.NumPlayers)
+ offset += 2
+ dest[offset] = elem.Load
+ offset++
+ dest[offset] = elem.NumberOnlineFlag
+ offset++
+ dest[offset] = elem.Unknown2
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], elem.AllowedRaces)
+ offset += 4
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldListV546) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1 + uint32(len(elem.Name2))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+
+ }
+
+ return size
+}
+
+// LSWorldListV562 represents packet structure for OP_WorldListMsg
+type LSWorldListV562 struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Name2 string `eq2:"name2,type:str16"`
+ Tag uint8 `eq2:"tag"`
+ Locked uint8 `eq2:"locked"`
+ Hidden uint8 `eq2:"hidden"`
+ Unknown uint8 `eq2:"unknown"`
+ NumPlayers uint16 `eq2:"num_players"`
+ Load uint8 `eq2:"load"`
+ NumberOnlineFlag uint8 `eq2:"number_online_flag"`
+ FeatureSet [2]uint8 `eq2:"feature_set,size:2"`
+ AllowedRaces uint32 `eq2:"allowed_races"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+ Unknown2 uint8 `eq2:"unknown2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldListV562) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ // Write Name2 string field
+ dest[offset] = byte(len(elem.Name2))
+ offset++
+ copy(dest[offset:], []byte(elem.Name2))
+ offset += uint32(len(elem.Name2))
+ dest[offset] = elem.Tag
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Hidden
+ offset++
+ dest[offset] = elem.Unknown
+ offset++
+ binary.LittleEndian.PutUint16(dest[offset:], elem.NumPlayers)
+ offset += 2
+ dest[offset] = elem.Load
+ offset++
+ dest[offset] = elem.NumberOnlineFlag
+ offset++
+ // Write FeatureSet array field
+ for i := 0; i < 2; i++ {
+ dest[offset] = byte(elem.FeatureSet[i])
+ offset++
+ }
+ binary.LittleEndian.PutUint32(dest[offset:], elem.AllowedRaces)
+ offset += 4
+
+ }
+
+ // Write Unknown2
+ dest[offset] = byte(p.Unknown2)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldListV562) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1 + uint32(len(elem.Name2))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 2
+ size += 1
+ size += 1
+ size += 2
+ size += 4
+
+ }
+
+ size += 1
+
+ return size
+}
+
+// LSWorldListV60114 represents packet structure for OP_WorldListMsg
+type LSWorldListV60114 struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Name2 string `eq2:"name2,type:str16"`
+ Tag uint8 `eq2:"tag"`
+ Locked uint8 `eq2:"locked"`
+ Hidden uint8 `eq2:"hidden"`
+ Unknown uint8 `eq2:"unknown"`
+ NumPlayers uint16 `eq2:"num_players"`
+ Load uint8 `eq2:"load"`
+ NumberOnlineFlag uint8 `eq2:"number_online_flag"`
+ FeatureSet [2]uint8 `eq2:"feature_set,size:2"`
+ AllowedRaces uint32 `eq2:"allowed_races"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+ Unknown2 uint8 `eq2:"unknown2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldListV60114) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ // Write Name2 string field
+ dest[offset] = byte(len(elem.Name2))
+ offset++
+ copy(dest[offset:], []byte(elem.Name2))
+ offset += uint32(len(elem.Name2))
+ dest[offset] = elem.Tag
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Hidden
+ offset++
+ dest[offset] = elem.Unknown
+ offset++
+ binary.LittleEndian.PutUint16(dest[offset:], elem.NumPlayers)
+ offset += 2
+ dest[offset] = elem.Load
+ offset++
+ dest[offset] = elem.NumberOnlineFlag
+ offset++
+ // Write FeatureSet array field
+ for i := 0; i < 2; i++ {
+ dest[offset] = byte(elem.FeatureSet[i])
+ offset++
+ }
+ binary.LittleEndian.PutUint32(dest[offset:], elem.AllowedRaces)
+ offset += 4
+
+ }
+
+ // Write Unknown2
+ dest[offset] = byte(p.Unknown2)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldListV60114) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1 + uint32(len(elem.Name2))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 2
+ size += 1
+ size += 1
+ size += 2
+ size += 4
+
+ }
+
+ size += 1
+
+ return size
+}
+
+// LSWorldListV65534 represents packet structure for OP_WorldListMsg
+type LSWorldListV65534 struct {
+ NumWorlds uint8 `eq2:"num_worlds"`
+ WorldList []struct {
+ Id uint32 `eq2:"id"`
+ Name string `eq2:"name,type:str16"`
+ Name2 string `eq2:"name2,type:str16"`
+ Tag uint8 `eq2:"tag"`
+ Locked uint8 `eq2:"locked"`
+ Hidden uint8 `eq2:"hidden"`
+ Unknown uint8 `eq2:"unknown"`
+ NumPlayers uint16 `eq2:"num_players"`
+ Load uint8 `eq2:"load"`
+ NumberOnlineFlag uint8 `eq2:"number_online_flag"`
+ FeatureSet [3]uint8 `eq2:"feature_set,size:3"`
+ AllowedRaces uint32 `eq2:"allowed_races"`
+ } `eq2:"world_list,sizeVar:num_worlds"`
+ Unknown2 uint8 `eq2:"unknown2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldListV65534) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write NumWorlds
+ dest[offset] = byte(p.NumWorlds)
+ offset++
+
+ // Write WorldList array (dynamic size)
+ for _, elem := range p.WorldList {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Id)
+ offset += 4
+ // Write Name string field
+ dest[offset] = byte(len(elem.Name))
+ offset++
+ copy(dest[offset:], []byte(elem.Name))
+ offset += uint32(len(elem.Name))
+ // Write Name2 string field
+ dest[offset] = byte(len(elem.Name2))
+ offset++
+ copy(dest[offset:], []byte(elem.Name2))
+ offset += uint32(len(elem.Name2))
+ dest[offset] = elem.Tag
+ offset++
+ dest[offset] = elem.Locked
+ offset++
+ dest[offset] = elem.Hidden
+ offset++
+ dest[offset] = elem.Unknown
+ offset++
+ binary.LittleEndian.PutUint16(dest[offset:], elem.NumPlayers)
+ offset += 2
+ dest[offset] = elem.Load
+ offset++
+ dest[offset] = elem.NumberOnlineFlag
+ offset++
+ // Write FeatureSet array field
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(elem.FeatureSet[i])
+ offset++
+ }
+ binary.LittleEndian.PutUint32(dest[offset:], elem.AllowedRaces)
+ offset += 4
+
+ }
+
+ // Write Unknown2
+ dest[offset] = byte(p.Unknown2)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldListV65534) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ // Dynamic array: WorldList
+ for _, elem := range p.WorldList {
+ _ = elem // Avoid unused variable warning
+ size += 4
+ size += 1 + uint32(len(elem.Name))
+ size += 1 + uint32(len(elem.Name2))
+ size += 1
+ size += 1
+ size += 1
+ size += 1
+ size += 2
+ size += 1
+ size += 1
+ size += 3
+ size += 4
+
+ }
+
+ size += 1
+
+ return size
+}
+
+// LSWorldUpdate represents packet structure for OP_WorldStatusChangeMsg
+type LSWorldUpdate struct {
+ ServerId uint32 `eq2:"server_id"`
+ Up uint8 `eq2:"up"`
+ Locked uint8 `eq2:"locked"`
+ Unknown1 uint8 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint8 `eq2:"unknown2"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSWorldUpdate) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Up
+ dest[offset] = byte(p.Up)
+ offset++
+
+ // Write Locked
+ dest[offset] = byte(p.Locked)
+ offset++
+
+ // Write Unknown1
+ dest[offset] = byte(p.Unknown1)
+ offset++
+
+ // Write Unknown2
+ dest[offset] = byte(p.Unknown2)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSWorldUpdate) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ return size
+}
+
+// LSPlayRequest represents packet structure for OP_PlayCharacterRequestMsg
+type LSPlayRequest struct {
+ CharId uint32 `eq2:"char_id"`
+ Name string `eq2:"name,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayRequest) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write CharId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CharId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayRequest) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ return size
+}
+
+// LSPlayRequestV284 represents packet structure for OP_PlayCharacterRequestMsg
+type LSPlayRequestV284 struct {
+ CharId uint32 `eq2:"char_id"`
+ ServerId uint32 `eq2:"server_id"`
+ Unknown [3]uint8 `eq2:"unknown,size:3"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayRequestV284) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write CharId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CharId))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Unknown array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayRequestV284) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ return size
+}
+
+// LSPlayResponse represents packet structure for OP_PlayCharacterReplyMsg
+type LSPlayResponse struct {
+ Response uint8 `eq2:"response"`
+ Server string `eq2:"server,type:str8"`
+ Port uint16 `eq2:"port"`
+ AccountId uint32 `eq2:"account_id"`
+ AccessCode uint32 `eq2:"access_code"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayResponse) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Server as 8-bit length-prefixed string
+ dest[offset] = byte(len(p.Server))
+ offset++
+ copy(dest[offset:], []byte(p.Server))
+ offset += uint32(len(p.Server))
+
+ // Write Port
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Port))
+ offset += 2
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write AccessCode
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccessCode))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayResponse) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 1 + uint32(len(p.Server))
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// LSPlayResponseV1096 represents packet structure for OP_PlayCharacterReplyMsg
+type LSPlayResponseV1096 struct {
+ Response uint8 `eq2:"response"`
+ Unknown1 uint16 `eq2:"unknown1"` // TODO: Identify purpose
+ Server string `eq2:"server,type:str8"`
+ Port uint16 `eq2:"port"`
+ AccountId uint32 `eq2:"account_id"`
+ AccessCode uint32 `eq2:"access_code"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayResponseV1096) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown1))
+ offset += 2
+
+ // Write Server as 8-bit length-prefixed string
+ dest[offset] = byte(len(p.Server))
+ offset++
+ copy(dest[offset:], []byte(p.Server))
+ offset += uint32(len(p.Server))
+
+ // Write Port
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Port))
+ offset += 2
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write AccessCode
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccessCode))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayResponseV1096) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2
+
+ size += 1 + uint32(len(p.Server))
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// LSPlayResponseV60085 represents packet structure for OP_PlayCharacterReplyMsg
+type LSPlayResponseV60085 struct {
+ Response uint8 `eq2:"response"`
+ Unknown1 [3]uint16 `eq2:"unknown1,size:3"` // TODO: Identify purpose
+ Server string `eq2:"server,type:str8"`
+ Port uint16 `eq2:"port"`
+ AccountId uint32 `eq2:"account_id"`
+ AccessCode uint32 `eq2:"access_code"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayResponseV60085) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Unknown1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown1[i]))
+ offset += 2
+ }
+
+ // Write Server as 8-bit length-prefixed string
+ dest[offset] = byte(len(p.Server))
+ offset++
+ copy(dest[offset:], []byte(p.Server))
+ offset += uint32(len(p.Server))
+
+ // Write Port
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Port))
+ offset += 2
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write AccessCode
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccessCode))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayResponseV60085) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 3 * 2
+
+ size += 1 + uint32(len(p.Server))
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// LSPlayResponseV60099 represents packet structure for OP_PlayCharacterReplyMsg
+type LSPlayResponseV60099 struct {
+ Response uint8 `eq2:"response"`
+ Unknown1 [3]uint16 `eq2:"unknown1,size:3"` // TODO: Identify purpose
+ Server string `eq2:"server,type:str8"`
+ Port uint16 `eq2:"port"`
+ AccountId uint32 `eq2:"account_id"`
+ AccessCode uint32 `eq2:"access_code"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSPlayResponseV60099) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Response
+ dest[offset] = byte(p.Response)
+ offset++
+
+ // Write Unknown1 array
+ for i := 0; i < 3; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown1[i]))
+ offset += 2
+ }
+
+ // Write Server as 8-bit length-prefixed string
+ dest[offset] = byte(len(p.Server))
+ offset++
+ copy(dest[offset:], []byte(p.Server))
+ offset += uint32(len(p.Server))
+
+ // Write Port
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Port))
+ offset += 2
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write AccessCode
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccessCode))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSPlayResponseV60099) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 3 * 2
+
+ size += 1 + uint32(len(p.Server))
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CharSelectProfile represents packet structure for client version 1
+type CharSelectProfile struct {
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Version uint8 `eq2:"version"`
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor [3]int8 `eq2:"skin_color,size:3"`
+ EyeColor [3]int8 `eq2:"eye_color,size:3"`
+ Equip [21]types.EquipmentItem `eq2:"equip,size:21"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor [3]int8 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]int8 `eq2:"hair_type_highlight_color,size:3"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor [3]int8 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]int8 `eq2:"hair_face_highlight_color,size:3"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor [3]int8 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]int8 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor [3]int8 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]int8 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]int8 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ BumpScale int8 `eq2:"bump_scale"`
+ Mount uint16 `eq2:"mount"`
+ MountColor1 [3]int8 `eq2:"mount_color1,size:3"`
+ MountColor2 [3]int8 `eq2:"mount_color2,size:3"`
+ HairColor1 [3]int8 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]int8 `eq2:"hair_color2,size:3"`
+ HairColor3 [3]int8 `eq2:"hair_color3,size:3"`
+ Flags uint8 `eq2:"flags"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfile) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SkinColor[i])
+ offset++
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeColor[i])
+ offset++
+ }
+
+ // Write Equip array
+ for i := 0; i < 21; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeColor[i])
+ offset++
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeHighlightColor[i])
+ offset++
+ }
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceColor[i])
+ offset++
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceHighlightColor[i])
+ offset++
+ }
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ShirtColor[i])
+ offset++
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownChestColor[i])
+ offset++
+ }
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.PantsColor[i])
+ offset++
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownLegsColor[i])
+ offset++
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.Unknown9[i])
+ offset++
+ }
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write BumpScale
+ dest[offset] = byte(p.BumpScale)
+ offset++
+
+ // Write Mount
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Mount))
+ offset += 2
+
+ // Write MountColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor1[i])
+ offset++
+ }
+
+ // Write MountColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor2[i])
+ offset++
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor1[i])
+ offset++
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor2[i])
+ offset++
+ }
+
+ // Write HairColor3 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor3[i])
+ offset++
+ }
+
+ // Write Flags
+ dest[offset] = byte(p.Flags)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfile) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 21 * 6
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ return size
+}
+
+// CharSelectProfileV373 represents packet structure for client version 373
+type CharSelectProfileV373 struct {
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Version uint8 `eq2:"version"`
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor [3]int8 `eq2:"skin_color,size:3"`
+ EyeColor [3]int8 `eq2:"eye_color,size:3"`
+ Equip [21]types.EquipmentItem `eq2:"equip,size:21"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor [3]int8 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]int8 `eq2:"hair_type_highlight_color,size:3"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor [3]int8 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]int8 `eq2:"hair_face_highlight_color,size:3"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor [3]int8 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]int8 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor [3]int8 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]int8 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]int8 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ BumpScale int8 `eq2:"bump_scale"`
+ Mount uint16 `eq2:"mount"`
+ MountColor1 [3]int8 `eq2:"mount_color1,size:3"`
+ MountColor2 [3]int8 `eq2:"mount_color2,size:3"`
+ HairColor1 [3]int8 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]int8 `eq2:"hair_color2,size:3"`
+ HairColor3 [3]int8 `eq2:"hair_color3,size:3"`
+ Flags uint8 `eq2:"flags"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfileV373) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SkinColor[i])
+ offset++
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeColor[i])
+ offset++
+ }
+
+ // Write Equip array
+ for i := 0; i < 21; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeColor[i])
+ offset++
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeHighlightColor[i])
+ offset++
+ }
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceColor[i])
+ offset++
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceHighlightColor[i])
+ offset++
+ }
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ShirtColor[i])
+ offset++
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownChestColor[i])
+ offset++
+ }
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.PantsColor[i])
+ offset++
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownLegsColor[i])
+ offset++
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.Unknown9[i])
+ offset++
+ }
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write BumpScale
+ dest[offset] = byte(p.BumpScale)
+ offset++
+
+ // Write Mount
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Mount))
+ offset += 2
+
+ // Write MountColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor1[i])
+ offset++
+ }
+
+ // Write MountColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor2[i])
+ offset++
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor1[i])
+ offset++
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor2[i])
+ offset++
+ }
+
+ // Write HairColor3 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor3[i])
+ offset++
+ }
+
+ // Write Flags
+ dest[offset] = byte(p.Flags)
+ offset++
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfileV373) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 21 * 6
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ return size
+}
+
+// CharSelectProfileV546 represents packet structure for client version 546
+type CharSelectProfileV546 struct {
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Gender uint8 `eq2:"gender"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Unknown5 uint32 `eq2:"unknown5"` // TODO: Identify purpose
+ Version uint8 `eq2:"version"`
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor [3]int8 `eq2:"skin_color,size:3"`
+ EyeColor [3]int8 `eq2:"eye_color,size:3"`
+ Equip [23]types.EquipmentItem `eq2:"equip,size:23"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor [3]int8 `eq2:"hair_type_color,size:3"`
+ HairTypeHighlightColor [3]int8 `eq2:"hair_type_highlight_color,size:3"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor [3]int8 `eq2:"hair_face_color,size:3"`
+ HairFaceHighlightColor [3]int8 `eq2:"hair_face_highlight_color,size:3"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor [3]int8 `eq2:"shirt_color,size:3"`
+ UnknownChestColor [3]int8 `eq2:"unknown_chest_color,size:3"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor [3]int8 `eq2:"pants_color,size:3"`
+ UnknownLegsColor [3]int8 `eq2:"unknown_legs_color,size:3"` // TODO: Identify purpose
+ Unknown9 [3]int8 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ BumpScale int8 `eq2:"bump_scale"`
+ Mount uint16 `eq2:"mount"`
+ MountColor1 [3]int8 `eq2:"mount_color1,size:3"`
+ MountColor2 [3]int8 `eq2:"mount_color2,size:3"`
+ HairColor1 [3]int8 `eq2:"hair_color1,size:3"`
+ HairColor2 [3]int8 `eq2:"hair_color2,size:3"`
+ HairColor3 [3]int8 `eq2:"hair_color3,size:3"`
+ Unknown11 [10]uint8 `eq2:"unknown11,size:10"` // TODO: Identify purpose
+ SogaRaceType uint16 `eq2:"soga_race_type"`
+ SogaSkinColorx types.Color `eq2:"soga_skin_colorx"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ Unknown12 [3]uint8 `eq2:"Unknown12,size:3"` // TODO: Identify purpose
+ SogaEyeType [3]int8 `eq2:"soga_eye_type,size:3"`
+ SogaEarType [3]int8 `eq2:"soga_ear_type,size:3"`
+ SogaEyeBrowType [3]int8 `eq2:"soga_eye_brow_type,size:3"`
+ SogaCheekType [3]int8 `eq2:"soga_cheek_type,size:3"`
+ SogaLipType [3]int8 `eq2:"soga_lip_type,size:3"`
+ SogaChinType [3]int8 `eq2:"soga_chin_type,size:3"`
+ SogaNoseType [3]int8 `eq2:"soga_nose_type,size:3"`
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaChestType uint16 `eq2:"soga_chest_type"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ SogaHairColor3 types.Color `eq2:"soga_hair_color3"`
+ SogaHairType uint16 `eq2:"soga_hair_type"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaHairFaceType uint16 `eq2:"soga_hair_face_type"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfileV546) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5))
+ offset += 4
+
+ // Write Version
+ dest[offset] = byte(p.Version)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SkinColor[i])
+ offset++
+ }
+
+ // Write EyeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeColor[i])
+ offset++
+ }
+
+ // Write Equip array
+ for i := 0; i < 23; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeColor[i])
+ offset++
+ }
+
+ // Write HairTypeHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairTypeHighlightColor[i])
+ offset++
+ }
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceColor[i])
+ offset++
+ }
+
+ // Write HairFaceHighlightColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairFaceHighlightColor[i])
+ offset++
+ }
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ShirtColor[i])
+ offset++
+ }
+
+ // Write UnknownChestColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownChestColor[i])
+ offset++
+ }
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.PantsColor[i])
+ offset++
+ }
+
+ // Write UnknownLegsColor array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.UnknownLegsColor[i])
+ offset++
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.Unknown9[i])
+ offset++
+ }
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write BumpScale
+ dest[offset] = byte(p.BumpScale)
+ offset++
+
+ // Write Mount
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Mount))
+ offset += 2
+
+ // Write MountColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor1[i])
+ offset++
+ }
+
+ // Write MountColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.MountColor2[i])
+ offset++
+ }
+
+ // Write HairColor1 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor1[i])
+ offset++
+ }
+
+ // Write HairColor2 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor2[i])
+ offset++
+ }
+
+ // Write HairColor3 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.HairColor3[i])
+ offset++
+ }
+
+ // Write Unknown11 array
+ for i := 0; i < 10; i++ {
+ dest[offset] = p.Unknown11[i]
+ offset++
+ }
+
+ // Write SogaRaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaRaceType))
+ offset += 2
+
+ // Write SogaSkinColorx
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColorx.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write Unknown12 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown12[i]
+ offset++
+ }
+
+ // Write SogaEyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeType[i])
+ offset++
+ }
+
+ // Write SogaEarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEarType[i])
+ offset++
+ }
+
+ // Write SogaEyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeBrowType[i])
+ offset++
+ }
+
+ // Write SogaCheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaCheekType[i])
+ offset++
+ }
+
+ // Write SogaLipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaLipType[i])
+ offset++
+ }
+
+ // Write SogaChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaChinType[i])
+ offset++
+ }
+
+ // Write SogaNoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaNoseType[i])
+ offset++
+ }
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaChestType))
+ offset += 2
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor3
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor3.ToUint32())
+ offset += 4
+
+ // Write SogaHairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairType))
+ offset += 2
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairFaceType))
+ offset += 2
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfileV546) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 4
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 23 * 6
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 10
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// CharSelectProfileV562 represents packet structure for client version 562
+type CharSelectProfileV562 struct {
+ Version uint32 `eq2:"version"`
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Unknown uint8 `eq2:"unknown"` // TODO: Identify purpose
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Gender uint8 `eq2:"gender"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Unknown5 uint32 `eq2:"unknown5"` // TODO: Identify purpose
+ ServerName string `eq2:"server_name,type:str16"`
+ AccountId uint32 `eq2:"account_id"`
+ Unknown6 [2]uint8 `eq2:"unknown6,size:2"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown8 uint8 `eq2:"unknown8"` // TODO: Identify purpose
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor types.Color `eq2:"skin_color"`
+ EyeColor types.Color `eq2:"eye_color"`
+ Equip [25]types.EquipmentItem `eq2:"equip,size:25"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ Unknown10 [9]uint8 `eq2:"unknown10,size:9"` // TODO: Identify purpose
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown11 [13]uint8 `eq2:"unknown11,size:13"` // TODO: Identify purpose
+ Unknown15 [7]uint8 `eq2:"unknown15,size:7"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfileV562) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Version
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Version))
+ offset += 4
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Unknown
+ dest[offset] = byte(p.Unknown)
+ offset++
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5))
+ offset += 4
+
+ // Write ServerName as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ServerName)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ServerName))
+ offset += uint32(len(p.ServerName))
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown6 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown8
+ dest[offset] = byte(p.Unknown8)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write Equip array
+ for i := 0; i < 25; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write Unknown10 array
+ for i := 0; i < 9; i++ {
+ dest[offset] = p.Unknown10[i]
+ offset++
+ }
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown11 array
+ for i := 0; i < 13; i++ {
+ dest[offset] = p.Unknown11[i]
+ offset++
+ }
+
+ // Write Unknown15 array
+ for i := 0; i < 7; i++ {
+ dest[offset] = p.Unknown15[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfileV562) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 4
+
+ size += 2 + uint32(len(p.ServerName))
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 1
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 25 * 6
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 9
+
+ size += 4
+
+ size += 4
+
+ size += 13
+
+ size += 7
+
+ return size
+}
+
+// CharSelectProfileV887 represents packet structure for client version 887
+type CharSelectProfileV887 struct {
+ Version uint32 `eq2:"version"`
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Unknown uint8 `eq2:"unknown"` // TODO: Identify purpose
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Gender uint8 `eq2:"gender"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Unknown5 uint32 `eq2:"unknown5"` // TODO: Identify purpose
+ ServerName string `eq2:"server_name,type:str16"`
+ AccountId uint32 `eq2:"account_id"`
+ Unknown6 [2]uint8 `eq2:"unknown6,size:2"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ TradeskillClass uint8 `eq2:"tradeskill_class"`
+ TradeskillLevel uint32 `eq2:"tradeskill_level"`
+ Unknown8 uint8 `eq2:"unknown8"` // TODO: Identify purpose
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor types.Color `eq2:"skin_color"`
+ EyeColor types.Color `eq2:"eye_color"`
+ Equip [25]types.EquipmentItem `eq2:"equip,size:25"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingType uint16 `eq2:"wing_type"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ Unknown10 [9]uint8 `eq2:"unknown10,size:9"` // TODO: Identify purpose
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown11 [13]uint8 `eq2:"unknown11,size:13"` // TODO: Identify purpose
+ SogaRaceType uint16 `eq2:"soga_race_type"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ Unknown12 [3]uint8 `eq2:"Unknown12,size:3"` // TODO: Identify purpose
+ SogaEyeType [3]int8 `eq2:"soga_eye_type,size:3"`
+ SogaEarType [3]int8 `eq2:"soga_ear_type,size:3"`
+ SogaEyeBrowType [3]int8 `eq2:"soga_eye_brow_type,size:3"`
+ SogaCheekType [3]int8 `eq2:"soga_cheek_type,size:3"`
+ SogaLipType [3]int8 `eq2:"soga_lip_type,size:3"`
+ SogaChinType [3]int8 `eq2:"soga_chin_type,size:3"`
+ SogaNoseType [3]int8 `eq2:"soga_nose_type,size:3"`
+ Unknown13 uint16 `eq2:"unknown13"` // TODO: Identify purpose
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ Unknown14 types.Color `eq2:"unknown14"` // TODO: Identify purpose
+ SogaHairType uint16 `eq2:"soga_hair_type"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaHairFaceType uint16 `eq2:"soga_hair_face_type"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ Unknown15 [7]uint8 `eq2:"unknown15,size:7"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfileV887) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Version
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Version))
+ offset += 4
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Unknown
+ dest[offset] = byte(p.Unknown)
+ offset++
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5))
+ offset += 4
+
+ // Write ServerName as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ServerName)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ServerName))
+ offset += uint32(len(p.ServerName))
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown6 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write TradeskillClass
+ dest[offset] = byte(p.TradeskillClass)
+ offset++
+
+ // Write TradeskillLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.TradeskillLevel))
+ offset += 4
+
+ // Write Unknown8
+ dest[offset] = byte(p.Unknown8)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write Equip array
+ for i := 0; i < 25; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.WingType))
+ offset += 2
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write Unknown10 array
+ for i := 0; i < 9; i++ {
+ dest[offset] = p.Unknown10[i]
+ offset++
+ }
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown11 array
+ for i := 0; i < 13; i++ {
+ dest[offset] = p.Unknown11[i]
+ offset++
+ }
+
+ // Write SogaRaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaRaceType))
+ offset += 2
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write Unknown12 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown12[i]
+ offset++
+ }
+
+ // Write SogaEyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeType[i])
+ offset++
+ }
+
+ // Write SogaEarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEarType[i])
+ offset++
+ }
+
+ // Write SogaEyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeBrowType[i])
+ offset++
+ }
+
+ // Write SogaCheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaCheekType[i])
+ offset++
+ }
+
+ // Write SogaLipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaLipType[i])
+ offset++
+ }
+
+ // Write SogaChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaChinType[i])
+ offset++
+ }
+
+ // Write SogaNoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaNoseType[i])
+ offset++
+ }
+
+ // Write Unknown13
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown13))
+ offset += 2
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown14
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown14.ToUint32())
+ offset += 4
+
+ // Write SogaHairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairType))
+ offset += 2
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairFaceType))
+ offset += 2
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write Unknown15 array
+ for i := 0; i < 7; i++ {
+ dest[offset] = p.Unknown15[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfileV887) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 4
+
+ size += 2 + uint32(len(p.ServerName))
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 1
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 25 * 6
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 9
+
+ size += 4
+
+ size += 4
+
+ size += 13
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 7
+
+ return size
+}
+
+// CharSelectProfileV60085 represents packet structure for client version 60085
+type CharSelectProfileV60085 struct {
+ Version uint32 `eq2:"version"`
+ Charid uint32 `eq2:"charid"`
+ ServerId uint32 `eq2:"server_id"`
+ Name string `eq2:"name,type:str16"`
+ Unknown uint8 `eq2:"unknown"` // TODO: Identify purpose
+ Race uint8 `eq2:"race"`
+ Class uint8 `eq2:"class"`
+ Gender uint8 `eq2:"gender"`
+ Level uint32 `eq2:"level"`
+ Zone string `eq2:"zone,type:str16"`
+ Unknown1 uint32 `eq2:"unknown1"` // TODO: Identify purpose
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ CreatedDate uint32 `eq2:"created_date"`
+ LastPlayed uint32 `eq2:"last_played"`
+ Unknown3 uint32 `eq2:"unknown3"` // TODO: Identify purpose
+ Unknown4 uint32 `eq2:"unknown4"` // TODO: Identify purpose
+ Zonename2 string `eq2:"zonename2,type:str16"`
+ Zonedesc string `eq2:"zonedesc,type:str16"`
+ Unknown5 uint32 `eq2:"unknown5"` // TODO: Identify purpose
+ ServerName string `eq2:"server_name,type:str16"`
+ AccountId uint32 `eq2:"account_id"`
+ Unknown6 [2]uint8 `eq2:"unknown6,size:2"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ TradeskillClass uint8 `eq2:"tradeskill_class"`
+ TradeskillLevel uint32 `eq2:"tradeskill_level"`
+ Unknown8 uint8 `eq2:"unknown8"` // TODO: Identify purpose
+ RaceType uint16 `eq2:"race_type"`
+ SkinColor types.Color `eq2:"skin_color"`
+ EyeColor types.Color `eq2:"eye_color"`
+ Equip [25]types.EquipmentItem `eq2:"equip,size:25"`
+ HairType uint16 `eq2:"hair_type"`
+ HairTypeColor types.Color `eq2:"hair_type_color"`
+ HairTypeHighlightColor types.Color `eq2:"hair_type_highlight_color"`
+ HairFaceType uint16 `eq2:"hair_face_type"`
+ HairFaceColor types.Color `eq2:"hair_face_color"`
+ HairFaceHighlightColor types.Color `eq2:"hair_face_highlight_color"`
+ WingType uint16 `eq2:"wing_type"`
+ WingColor1 types.Color `eq2:"wing_color1"`
+ WingColor2 types.Color `eq2:"wing_color2"`
+ ChestType uint16 `eq2:"chest_type"`
+ ShirtColor types.Color `eq2:"shirt_color"`
+ UnknownChestColor types.Color `eq2:"unknown_chest_color"` // TODO: Identify purpose
+ LegsType uint16 `eq2:"legs_type"`
+ PantsColor types.Color `eq2:"pants_color"`
+ UnknownLegsColor types.Color `eq2:"unknown_legs_color"` // TODO: Identify purpose
+ Unknown9 types.Color `eq2:"unknown9"` // TODO: Identify purpose
+ EyeType [3]int8 `eq2:"eye_type,size:3"`
+ EarType [3]int8 `eq2:"ear_type,size:3"`
+ EyeBrowType [3]int8 `eq2:"eye_brow_type,size:3"`
+ CheekType [3]int8 `eq2:"cheek_type,size:3"`
+ LipType [3]int8 `eq2:"lip_type,size:3"`
+ ChinType [3]int8 `eq2:"chin_type,size:3"`
+ NoseType [3]int8 `eq2:"nose_type,size:3"`
+ BodySize int8 `eq2:"body_size"`
+ Unknown10 [9]uint8 `eq2:"unknown10,size:9"` // TODO: Identify purpose
+ HairColor1 types.Color `eq2:"hair_color1"`
+ HairColor2 types.Color `eq2:"hair_color2"`
+ Unknown11 [13]uint8 `eq2:"unknown11,size:13"` // TODO: Identify purpose
+ SogaRaceType uint16 `eq2:"soga_race_type"`
+ SogaSkinColor types.Color `eq2:"soga_skin_color"`
+ SogaEyeColor types.Color `eq2:"soga_eye_color"`
+ Unknown12 [3]uint8 `eq2:"Unknown12,size:3"` // TODO: Identify purpose
+ SogaEyeType [3]int8 `eq2:"soga_eye_type,size:3"`
+ SogaEarType [3]int8 `eq2:"soga_ear_type,size:3"`
+ SogaEyeBrowType [3]int8 `eq2:"soga_eye_brow_type,size:3"`
+ SogaCheekType [3]int8 `eq2:"soga_cheek_type,size:3"`
+ SogaLipType [3]int8 `eq2:"soga_lip_type,size:3"`
+ SogaChinType [3]int8 `eq2:"soga_chin_type,size:3"`
+ SogaNoseType [3]int8 `eq2:"soga_nose_type,size:3"`
+ Unknown13 uint16 `eq2:"unknown13"` // TODO: Identify purpose
+ SogaHairColor1 types.Color `eq2:"soga_hair_color1"`
+ SogaHairColor2 types.Color `eq2:"soga_hair_color2"`
+ Unknown14 types.Color `eq2:"unknown14"` // TODO: Identify purpose
+ SogaHairType uint16 `eq2:"soga_hair_type"`
+ SogaHairTypeColor types.Color `eq2:"soga_hair_type_color"`
+ SogaHairTypeHighlightColor types.Color `eq2:"soga_hair_type_highlight_color"`
+ SogaHairFaceType uint16 `eq2:"soga_hair_face_type"`
+ SogaHairFaceColor types.Color `eq2:"soga_hair_face_color"`
+ SogaHairFaceHighlightColor types.Color `eq2:"soga_hair_face_highlight_color"`
+ Unknown15 [7]uint8 `eq2:"unknown15,size:7"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *CharSelectProfileV60085) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write Version
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Version))
+ offset += 4
+
+ // Write Charid
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Charid))
+ offset += 4
+
+ // Write ServerId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ServerId))
+ offset += 4
+
+ // Write Name as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Name)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Name))
+ offset += uint32(len(p.Name))
+
+ // Write Unknown
+ dest[offset] = byte(p.Unknown)
+ offset++
+
+ // Write Race
+ dest[offset] = byte(p.Race)
+ offset++
+
+ // Write Class
+ dest[offset] = byte(p.Class)
+ offset++
+
+ // Write Gender
+ dest[offset] = byte(p.Gender)
+ offset++
+
+ // Write Level
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Level))
+ offset += 4
+
+ // Write Zone as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zone)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zone))
+ offset += uint32(len(p.Zone))
+
+ // Write Unknown1
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown1))
+ offset += 4
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write CreatedDate
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CreatedDate))
+ offset += 4
+
+ // Write LastPlayed
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.LastPlayed))
+ offset += 4
+
+ // Write Unknown3
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown3))
+ offset += 4
+
+ // Write Unknown4
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown4))
+ offset += 4
+
+ // Write Zonename2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonename2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonename2))
+ offset += uint32(len(p.Zonename2))
+
+ // Write Zonedesc as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Zonedesc)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Zonedesc))
+ offset += uint32(len(p.Zonedesc))
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown5))
+ offset += 4
+
+ // Write ServerName as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.ServerName)))
+ offset += 2
+ copy(dest[offset:], []byte(p.ServerName))
+ offset += uint32(len(p.ServerName))
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown6 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write TradeskillClass
+ dest[offset] = byte(p.TradeskillClass)
+ offset++
+
+ // Write TradeskillLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.TradeskillLevel))
+ offset += 4
+
+ // Write Unknown8
+ dest[offset] = byte(p.Unknown8)
+ offset++
+
+ // Write RaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.RaceType))
+ offset += 2
+
+ // Write SkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SkinColor.ToUint32())
+ offset += 4
+
+ // Write EyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.EyeColor.ToUint32())
+ offset += 4
+
+ // Write Equip array
+ for i := 0; i < 25; i++ {
+ binary.LittleEndian.PutUint16(dest[offset:], p.Equip[i].Type)
+ offset += 2
+ binary.LittleEndian.PutUint32(dest[offset:], p.Equip[i].Color.ToUint32())
+ offset += 4
+ }
+
+ // Write HairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairType))
+ offset += 2
+
+ // Write HairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeColor.ToUint32())
+ offset += 4
+
+ // Write HairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.HairFaceType))
+ offset += 2
+
+ // Write HairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceColor.ToUint32())
+ offset += 4
+
+ // Write HairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write WingType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.WingType))
+ offset += 2
+
+ // Write WingColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor1.ToUint32())
+ offset += 4
+
+ // Write WingColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.WingColor2.ToUint32())
+ offset += 4
+
+ // Write ChestType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.ChestType))
+ offset += 2
+
+ // Write ShirtColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.ShirtColor.ToUint32())
+ offset += 4
+
+ // Write UnknownChestColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownChestColor.ToUint32())
+ offset += 4
+
+ // Write LegsType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.LegsType))
+ offset += 2
+
+ // Write PantsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.PantsColor.ToUint32())
+ offset += 4
+
+ // Write UnknownLegsColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.UnknownLegsColor.ToUint32())
+ offset += 4
+
+ // Write Unknown9
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown9.ToUint32())
+ offset += 4
+
+ // Write EyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeType[i])
+ offset++
+ }
+
+ // Write EarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EarType[i])
+ offset++
+ }
+
+ // Write EyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.EyeBrowType[i])
+ offset++
+ }
+
+ // Write CheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.CheekType[i])
+ offset++
+ }
+
+ // Write LipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.LipType[i])
+ offset++
+ }
+
+ // Write ChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.ChinType[i])
+ offset++
+ }
+
+ // Write NoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.NoseType[i])
+ offset++
+ }
+
+ // Write BodySize
+ dest[offset] = byte(p.BodySize)
+ offset++
+
+ // Write Unknown10 array
+ for i := 0; i < 9; i++ {
+ dest[offset] = p.Unknown10[i]
+ offset++
+ }
+
+ // Write HairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor1.ToUint32())
+ offset += 4
+
+ // Write HairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.HairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown11 array
+ for i := 0; i < 13; i++ {
+ dest[offset] = p.Unknown11[i]
+ offset++
+ }
+
+ // Write SogaRaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaRaceType))
+ offset += 2
+
+ // Write SogaSkinColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaSkinColor.ToUint32())
+ offset += 4
+
+ // Write SogaEyeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaEyeColor.ToUint32())
+ offset += 4
+
+ // Write Unknown12 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown12[i]
+ offset++
+ }
+
+ // Write SogaEyeType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeType[i])
+ offset++
+ }
+
+ // Write SogaEarType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEarType[i])
+ offset++
+ }
+
+ // Write SogaEyeBrowType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaEyeBrowType[i])
+ offset++
+ }
+
+ // Write SogaCheekType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaCheekType[i])
+ offset++
+ }
+
+ // Write SogaLipType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaLipType[i])
+ offset++
+ }
+
+ // Write SogaChinType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaChinType[i])
+ offset++
+ }
+
+ // Write SogaNoseType array
+ for i := 0; i < 3; i++ {
+ dest[offset] = byte(p.SogaNoseType[i])
+ offset++
+ }
+
+ // Write Unknown13
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown13))
+ offset += 2
+
+ // Write SogaHairColor1
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor1.ToUint32())
+ offset += 4
+
+ // Write SogaHairColor2
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairColor2.ToUint32())
+ offset += 4
+
+ // Write Unknown14
+ binary.LittleEndian.PutUint32(dest[offset:], p.Unknown14.ToUint32())
+ offset += 4
+
+ // Write SogaHairType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairType))
+ offset += 2
+
+ // Write SogaHairTypeColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairTypeHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairTypeHighlightColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceType
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.SogaHairFaceType))
+ offset += 2
+
+ // Write SogaHairFaceColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceColor.ToUint32())
+ offset += 4
+
+ // Write SogaHairFaceHighlightColor
+ binary.LittleEndian.PutUint32(dest[offset:], p.SogaHairFaceHighlightColor.ToUint32())
+ offset += 4
+
+ // Write Unknown15 array
+ for i := 0; i < 7; i++ {
+ dest[offset] = p.Unknown15[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *CharSelectProfileV60085) Size() uint32 {
+ size := uint32(0)
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Name))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zone))
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Zonename2))
+
+ size += 2 + uint32(len(p.Zonedesc))
+
+ size += 4
+
+ size += 2 + uint32(len(p.ServerName))
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 1
+
+ size += 4
+
+ size += 1
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 25 * 6
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 9
+
+ size += 4
+
+ size += 4
+
+ size += 13
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 3
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 2
+
+ size += 4
+
+ size += 4
+
+ size += 7
+
+ return size
+}
+
+// LSLoginReplyMsg represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsg struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ WorldName string `eq2:"worldName,type:str16"`
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer [2]uint32 `eq2:"parental_control_timer,size:2"`
+ ParentalControlNext uint32 `eq2:"parental_control_next"`
+ AccountId uint32 `eq2:"account_id"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsg) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write WorldName as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WorldName)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WorldName))
+ offset += uint32(len(p.WorldName))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer array
+ for i := 0; i < 2; i++ {
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer[i]))
+ offset += 4
+ }
+
+ // Write ParentalControlNext
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlNext))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsg) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.WorldName))
+
+ size += 1
+
+ size += 2 * 4
+
+ size += 4
+
+ size += 4
+
+ return size
+}
+
+// LSLoginReplyMsgV284 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV284 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ CacheSettingAccountId uint32 `eq2:"cache_setting_account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 uint8 `eq2:"unknown6"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown8 [2]uint8 `eq2:"unknown8,size:2"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint16 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV284) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write CacheSettingAccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.CacheSettingAccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6
+ dest[offset] = byte(p.Unknown6)
+ offset++
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown8 array
+ for i := 0; i < 2; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.ModelId)
+ offset += 2
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV284) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 1
+
+ size += 4
+
+ size += 2
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ return size
+}
+
+// LSLoginReplyMsgV843 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV843 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 uint8 `eq2:"unknown6"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 uint8 `eq2:"unknown9"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint16 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV843) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6
+ dest[offset] = byte(p.Unknown6)
+ offset++
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9
+ dest[offset] = byte(p.Unknown9)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.ModelId)
+ offset += 2
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV843) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 1
+
+ size += 4
+
+ size += 1
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ return size
+}
+
+// LSLoginReplyMsgV1096 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV1096 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 [5]uint8 `eq2:"unknown6,size:5"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 uint8 `eq2:"unknown9"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint16 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV1096) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9
+ dest[offset] = byte(p.Unknown9)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.ModelId)
+ offset += 2
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV1096) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 5
+
+ size += 4
+
+ size += 1
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ return size
+}
+
+// LSLoginReplyMsgV1142 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV1142 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 [5]uint8 `eq2:"unknown6,size:5"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown7a uint32 `eq2:"unknown7a"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 uint8 `eq2:"unknown9"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint16 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV1142) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown7a
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7a))
+ offset += 4
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9
+ dest[offset] = byte(p.Unknown9)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.ModelId)
+ offset += 2
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV1142) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 5
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ return size
+}
+
+// LSLoginReplyMsgV1188 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV1188 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 [5]uint8 `eq2:"unknown6,size:5"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown7a uint32 `eq2:"unknown7a"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 uint8 `eq2:"unknown9"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint16 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Unknown12 string `eq2:"unknown12,type:str16"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV1188) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown7a
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7a))
+ offset += 4
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9
+ dest[offset] = byte(p.Unknown9)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint16(dest[offset:], nestedElem.ModelId)
+ offset += 2
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Unknown12 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown12)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown12))
+ offset += uint32(len(p.Unknown12))
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV1188) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 5
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 2
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Unknown12))
+
+ return size
+}
+
+// LSLoginReplyMsgV57080 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV57080 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 [5]uint8 `eq2:"unknown6,size:5"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown7a uint32 `eq2:"unknown7a"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 uint8 `eq2:"unknown9"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Service string `eq2:"service,type:str16"`
+ Web1 string `eq2:"web1,type:str16"`
+ Web2 string `eq2:"web2,type:str16"`
+ Web3 string `eq2:"web3,type:str16"`
+ Web4 string `eq2:"web4,type:str16"`
+ Web5 string `eq2:"web5,type:str16"`
+ Web6 string `eq2:"web6,type:str16"`
+ Web7 string `eq2:"web7,type:str16"`
+ Web8 string `eq2:"web8,type:str16"`
+ Web9 string `eq2:"web9,type:str16"`
+ Unknown12 uint8 `eq2:"unknown12"` // TODO: Identify purpose
+ Lvl90NumClassItems uint8 `eq2:"lvl90_num_class_items,ifSet:unknown10"`
+ Lvl90ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"lvl90_class_items,sizeVar:lvl90_num_class_items,ifSet:unknown10"`
+ Unknown13 [5]uint8 `eq2:"unknown13,size:5"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV57080) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown7a
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7a))
+ offset += 4
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9
+ dest[offset] = byte(p.Unknown9)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Service as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Service)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Service))
+ offset += uint32(len(p.Service))
+
+ // Write Web1 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web1)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web1))
+ offset += uint32(len(p.Web1))
+
+ // Write Web2 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web2)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web2))
+ offset += uint32(len(p.Web2))
+
+ // Write Web3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web3))
+ offset += uint32(len(p.Web3))
+
+ // Write Web4 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web4)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web4))
+ offset += uint32(len(p.Web4))
+
+ // Write Web5 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web5)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web5))
+ offset += uint32(len(p.Web5))
+
+ // Write Web6 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web6)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web6))
+ offset += uint32(len(p.Web6))
+
+ // Write Web7 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web7)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web7))
+ offset += uint32(len(p.Web7))
+
+ // Write Web8 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web8)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web8))
+ offset += uint32(len(p.Web8))
+
+ // Write Web9 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Web9)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Web9))
+ offset += uint32(len(p.Web9))
+
+ // Write Unknown12
+ dest[offset] = byte(p.Unknown12)
+ offset++
+
+ // Write Lvl90NumClassItems
+ dest[offset] = byte(p.Lvl90NumClassItems)
+ offset++
+
+ // Write Lvl90ClassItems array (dynamic size)
+ for _, elem := range p.Lvl90ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown13 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown13[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV57080) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 5
+
+ size += 4
+
+ size += 4
+
+ size += 1
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Service))
+
+ size += 2 + uint32(len(p.Web1))
+
+ size += 2 + uint32(len(p.Web2))
+
+ size += 2 + uint32(len(p.Web3))
+
+ size += 2 + uint32(len(p.Web4))
+
+ size += 2 + uint32(len(p.Web5))
+
+ size += 2 + uint32(len(p.Web6))
+
+ size += 2 + uint32(len(p.Web7))
+
+ size += 2 + uint32(len(p.Web8))
+
+ size += 2 + uint32(len(p.Web9))
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: Lvl90ClassItems
+ for _, elem := range p.Lvl90ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 5
+
+ return size
+}
+
+// LSLoginReplyMsgV60100 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV60100 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown5 int64 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown7a uint16 `eq2:"unknown7a"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 [3]uint8 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Service string `eq2:"service,type:str16"`
+ Unknown12 uint8 `eq2:"unknown12"` // TODO: Identify purpose
+ Lvl90NumClassItems uint8 `eq2:"lvl90_num_class_items,ifSet:unknown12"`
+ Lvl90ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"lvl90_class_items,sizeVar:lvl90_num_class_items,ifSet:unknown12"`
+ Unknown13 uint8 `eq2:"unknown13"` // TODO: Identify purpose
+ TimeLockedNumClassItems uint8 `eq2:"time_locked_num_class_items,ifSet:unknown13"`
+ TimeLockedClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"time_locked_class_items,sizeVar:time_locked_num_class_items,ifSet:unknown13"`
+ Unknown14 [13]uint8 `eq2:"unknown14,size:13"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV60100) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint64(dest[offset:], uint64(p.Unknown5))
+ offset += 8
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown7a
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown7a))
+ offset += 2
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown9[i]
+ offset++
+ }
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Service as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Service)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Service))
+ offset += uint32(len(p.Service))
+
+ // Write Unknown12
+ dest[offset] = byte(p.Unknown12)
+ offset++
+
+ // Write Lvl90NumClassItems
+ dest[offset] = byte(p.Lvl90NumClassItems)
+ offset++
+
+ // Write Lvl90ClassItems array (dynamic size)
+ for _, elem := range p.Lvl90ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown13
+ dest[offset] = byte(p.Unknown13)
+ offset++
+
+ // Write TimeLockedNumClassItems
+ dest[offset] = byte(p.TimeLockedNumClassItems)
+ offset++
+
+ // Write TimeLockedClassItems array (dynamic size)
+ for _, elem := range p.TimeLockedClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown14 array
+ for i := 0; i < 13; i++ {
+ dest[offset] = p.Unknown14[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV60100) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 8
+
+ size += 4
+
+ size += 2
+
+ size += 1
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Service))
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: Lvl90ClassItems
+ for _, elem := range p.Lvl90ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: TimeLockedClassItems
+ for _, elem := range p.TimeLockedClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 13
+
+ return size
+}
+
+// LSLoginReplyMsgV63181 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV63181 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ Unknown string `eq2:"unknown,type:str16"` // TODO: Identify purpose
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer uint32 `eq2:"parental_control_timer"`
+ Unknown2 [8]uint8 `eq2:"unknown2,size:8"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 uint8 `eq2:"unknown4"` // TODO: Identify purpose
+ Unknown5 uint16 `eq2:"unknown5"` // TODO: Identify purpose
+ Unknown6 [5]uint8 `eq2:"unknown6,size:5"` // TODO: Identify purpose
+ Unknown6a [8]uint8 `eq2:"unknown6a,size:8"` // TODO: Identify purpose
+ Unknown7 uint32 `eq2:"unknown7"` // TODO: Identify purpose
+ Unknown7a uint16 `eq2:"unknown7a"` // TODO: Identify purpose
+ RaceUnknown uint8 `eq2:"race_unknown"`
+ Unknown8 [3]uint8 `eq2:"unknown8,size:3"` // TODO: Identify purpose
+ Unknown9 [3]uint8 `eq2:"unknown9,size:3"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Service string `eq2:"service,type:str16"`
+ Unknown12 uint8 `eq2:"unknown12"` // TODO: Identify purpose
+ Lvl90NumClassItems uint8 `eq2:"lvl90_num_class_items,ifSet:unknown12"`
+ Lvl90ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"lvl90_class_items,sizeVar:lvl90_num_class_items,ifSet:unknown12"`
+ Unknown13 uint8 `eq2:"unknown13"` // TODO: Identify purpose
+ TimeLockedNumClassItems uint8 `eq2:"time_locked_num_class_items,ifSet:unknown13"`
+ TimeLockedClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"time_locked_class_items,sizeVar:time_locked_num_class_items,ifSet:unknown13"`
+ Unknown14 [9]uint8 `eq2:"unknown14,size:9"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV63181) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write Unknown as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown))
+ offset += uint32(len(p.Unknown))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ParentalControlTimer))
+ offset += 4
+
+ // Write Unknown2 array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown2[i]
+ offset++
+ }
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4
+ dest[offset] = byte(p.Unknown4)
+ offset++
+
+ // Write Unknown5
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown5))
+ offset += 2
+
+ // Write Unknown6 array
+ for i := 0; i < 5; i++ {
+ dest[offset] = p.Unknown6[i]
+ offset++
+ }
+
+ // Write Unknown6a array
+ for i := 0; i < 8; i++ {
+ dest[offset] = p.Unknown6a[i]
+ offset++
+ }
+
+ // Write Unknown7
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown7))
+ offset += 4
+
+ // Write Unknown7a
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(p.Unknown7a))
+ offset += 2
+
+ // Write RaceUnknown
+ dest[offset] = byte(p.RaceUnknown)
+ offset++
+
+ // Write Unknown8 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown8[i]
+ offset++
+ }
+
+ // Write Unknown9 array
+ for i := 0; i < 3; i++ {
+ dest[offset] = p.Unknown9[i]
+ offset++
+ }
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Service as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Service)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Service))
+ offset += uint32(len(p.Service))
+
+ // Write Unknown12
+ dest[offset] = byte(p.Unknown12)
+ offset++
+
+ // Write Lvl90NumClassItems
+ dest[offset] = byte(p.Lvl90NumClassItems)
+ offset++
+
+ // Write Lvl90ClassItems array (dynamic size)
+ for _, elem := range p.Lvl90ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown13
+ dest[offset] = byte(p.Unknown13)
+ offset++
+
+ // Write TimeLockedNumClassItems
+ dest[offset] = byte(p.TimeLockedNumClassItems)
+ offset++
+
+ // Write TimeLockedClassItems array (dynamic size)
+ for _, elem := range p.TimeLockedClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown14 array
+ for i := 0; i < 9; i++ {
+ dest[offset] = p.Unknown14[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV63181) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.Unknown))
+
+ size += 1
+
+ size += 4
+
+ size += 8
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ size += 2
+
+ size += 5
+
+ size += 8
+
+ size += 4
+
+ size += 2
+
+ size += 1
+
+ size += 3
+
+ size += 3
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Service))
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: Lvl90ClassItems
+ for _, elem := range p.Lvl90ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: TimeLockedClassItems
+ for _, elem := range p.TimeLockedClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 9
+
+ return size
+}
+
+// LSLoginReplyMsgV65534 represents packet structure for OP_LoginReplyMsg
+type LSLoginReplyMsgV65534 struct {
+ LoginResponse uint8 `eq2:"login_response"`
+ WorldName string `eq2:"world_name,type:str16"`
+ ParentalControlFlag uint8 `eq2:"parental_control_flag"`
+ ParentalControlTimer int64 `eq2:"parental_control_timer"`
+ Unknown2 uint32 `eq2:"unknown2"` // TODO: Identify purpose
+ AccountId uint32 `eq2:"account_id"`
+ Unknown3 string `eq2:"unknown3,type:str16"` // TODO: Identify purpose
+ ResetAppearance uint8 `eq2:"reset_appearance"`
+ DoNotForceSoga uint8 `eq2:"do_not_force_soga"`
+ Unknown4 string `eq2:"unknown4,type:EQ2_32Bit_String"` // TODO: Identify purpose
+ Unknown7 string `eq2:"unknown7,type:EQ2_32Bit_String"` // TODO: Identify purpose
+ RaceUnknown uint32 `eq2:"race_unknown"`
+ Unknown8 uint8 `eq2:"unknown8"` // TODO: Identify purpose
+ Unknown10 uint8 `eq2:"unknown10"` // TODO: Identify purpose
+ NumClassItems uint8 `eq2:"num_class_items,ifSet:unknown10"`
+ ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"class_items,sizeVar:num_class_items,ifSet:unknown10"`
+ UnknownArray2Size uint8 `eq2:"unknown_array2_size"` // TODO: Identify purpose
+ UnknownArray2 []struct {
+ Array2Unknown uint32 `eq2:"array2_unknown"`
+ } `eq2:"unknown_array2,sizeVar:unknown_array2_size,ifSet:unknown_array2_size"`
+ Unknown11 uint32 `eq2:"unknown11"` // TODO: Identify purpose
+ SubLevel uint32 `eq2:"sub_level"`
+ RaceFlag uint32 `eq2:"race_flag"`
+ ClassFlag uint32 `eq2:"class_flag"`
+ Password string `eq2:"password,type:str16"`
+ Username string `eq2:"username,type:str16"`
+ Service string `eq2:"service,type:str16"`
+ Unknown12 uint8 `eq2:"unknown12"` // TODO: Identify purpose
+ Lvl90NumClassItems uint8 `eq2:"lvl90_num_class_items,ifSet:unknown12"`
+ Lvl90ClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"lvl90_class_items,sizeVar:lvl90_num_class_items,ifSet:unknown12"`
+ Unknown13 uint8 `eq2:"unknown13"` // TODO: Identify purpose
+ TimeLockedNumClassItems uint8 `eq2:"time_locked_num_class_items,ifSet:unknown13"`
+ TimeLockedClassItems []struct {
+ ClassId uint8 `eq2:"class_id"`
+ NumItems uint8 `eq2:"num_items"`
+ StartingItems []struct {
+ ModelId uint32 `eq2:"model_id"`
+ SlotId uint8 `eq2:"slot_id"`
+ UseColor uint8 `eq2:"use_color"`
+ UseHighlightColor uint8 `eq2:"use_highlight_color"`
+ ModelColor types.Color `eq2:"model_color"`
+ ModelHighlightColor types.Color `eq2:"model_highlight_color"`
+ } `eq2:"starting_items"`
+ } `eq2:"time_locked_class_items,sizeVar:time_locked_num_class_items,ifSet:unknown13"`
+ Unknown14 [13]uint8 `eq2:"unknown14,size:13"` // TODO: Identify purpose
+}
+
+// Serialize writes the packet data to the provided buffer
+func (p *LSLoginReplyMsgV65534) Serialize(dest []byte) uint32 {
+ offset := uint32(0)
+
+ // Write LoginResponse
+ dest[offset] = byte(p.LoginResponse)
+ offset++
+
+ // Write WorldName as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.WorldName)))
+ offset += 2
+ copy(dest[offset:], []byte(p.WorldName))
+ offset += uint32(len(p.WorldName))
+
+ // Write ParentalControlFlag
+ dest[offset] = byte(p.ParentalControlFlag)
+ offset++
+
+ // Write ParentalControlTimer
+ binary.LittleEndian.PutUint64(dest[offset:], uint64(p.ParentalControlTimer))
+ offset += 8
+
+ // Write Unknown2
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown2))
+ offset += 4
+
+ // Write AccountId
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.AccountId))
+ offset += 4
+
+ // Write Unknown3 as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Unknown3)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Unknown3))
+ offset += uint32(len(p.Unknown3))
+
+ // Write ResetAppearance
+ dest[offset] = byte(p.ResetAppearance)
+ offset++
+
+ // Write DoNotForceSoga
+ dest[offset] = byte(p.DoNotForceSoga)
+ offset++
+
+ // Write Unknown4 as 32-bit length-prefixed string
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(len(p.Unknown4)))
+ offset += 4
+ copy(dest[offset:], []byte(p.Unknown4))
+ offset += uint32(len(p.Unknown4))
+
+ // Write Unknown7 as 32-bit length-prefixed string
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(len(p.Unknown7)))
+ offset += 4
+ copy(dest[offset:], []byte(p.Unknown7))
+ offset += uint32(len(p.Unknown7))
+
+ // Write RaceUnknown
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceUnknown))
+ offset += 4
+
+ // Write Unknown8
+ dest[offset] = byte(p.Unknown8)
+ offset++
+
+ // Write Unknown10
+ dest[offset] = byte(p.Unknown10)
+ offset++
+
+ // Write NumClassItems
+ dest[offset] = byte(p.NumClassItems)
+ offset++
+
+ // Write ClassItems array (dynamic size)
+ for _, elem := range p.ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write UnknownArray2Size
+ dest[offset] = byte(p.UnknownArray2Size)
+ offset++
+
+ // Write UnknownArray2 array (dynamic size)
+ for _, elem := range p.UnknownArray2 {
+ binary.LittleEndian.PutUint32(dest[offset:], elem.Array2Unknown)
+ offset += 4
+
+ }
+
+ // Write Unknown11
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.Unknown11))
+ offset += 4
+
+ // Write SubLevel
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.SubLevel))
+ offset += 4
+
+ // Write RaceFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.RaceFlag))
+ offset += 4
+
+ // Write ClassFlag
+ binary.LittleEndian.PutUint32(dest[offset:], uint32(p.ClassFlag))
+ offset += 4
+
+ // Write Password as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Password)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Password))
+ offset += uint32(len(p.Password))
+
+ // Write Username as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Username)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Username))
+ offset += uint32(len(p.Username))
+
+ // Write Service as 16-bit length-prefixed string
+ binary.LittleEndian.PutUint16(dest[offset:], uint16(len(p.Service)))
+ offset += 2
+ copy(dest[offset:], []byte(p.Service))
+ offset += uint32(len(p.Service))
+
+ // Write Unknown12
+ dest[offset] = byte(p.Unknown12)
+ offset++
+
+ // Write Lvl90NumClassItems
+ dest[offset] = byte(p.Lvl90NumClassItems)
+ offset++
+
+ // Write Lvl90ClassItems array (dynamic size)
+ for _, elem := range p.Lvl90ClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown13
+ dest[offset] = byte(p.Unknown13)
+ offset++
+
+ // Write TimeLockedNumClassItems
+ dest[offset] = byte(p.TimeLockedNumClassItems)
+ offset++
+
+ // Write TimeLockedClassItems array (dynamic size)
+ for _, elem := range p.TimeLockedClassItems {
+ dest[offset] = elem.ClassId
+ offset++
+ dest[offset] = elem.NumItems
+ offset++
+ // Write nested StartingItems array
+ for _, nestedElem := range elem.StartingItems {
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelId)
+ offset += 4
+ dest[offset] = nestedElem.SlotId
+ offset++
+ dest[offset] = nestedElem.UseColor
+ offset++
+ dest[offset] = nestedElem.UseHighlightColor
+ offset++
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelColor.ToUint32())
+ offset += 4
+ binary.LittleEndian.PutUint32(dest[offset:], nestedElem.ModelHighlightColor.ToUint32())
+ offset += 4
+
+ }
+
+ }
+
+ // Write Unknown14 array
+ for i := 0; i < 13; i++ {
+ dest[offset] = p.Unknown14[i]
+ offset++
+ }
+
+ return offset
+}
+
+// Size returns the serialized size of the packet
+func (p *LSLoginReplyMsgV65534) Size() uint32 {
+ size := uint32(0)
+
+ size += 1
+
+ size += 2 + uint32(len(p.WorldName))
+
+ size += 1
+
+ size += 8
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Unknown3))
+
+ size += 1
+
+ size += 1
+
+ size += 4 + uint32(len(p.Unknown4))
+
+ size += 4 + uint32(len(p.Unknown7))
+
+ size += 4
+
+ size += 1
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: ClassItems
+ for _, elem := range p.ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ // Dynamic array: UnknownArray2
+ for _, elem := range p.UnknownArray2 {
+ _ = elem // Avoid unused variable warning
+ size += 4
+
+ }
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 4
+
+ size += 2 + uint32(len(p.Password))
+
+ size += 2 + uint32(len(p.Username))
+
+ size += 2 + uint32(len(p.Service))
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: Lvl90ClassItems
+ for _, elem := range p.Lvl90ClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 1
+
+ size += 1
+
+ // Dynamic array: TimeLockedClassItems
+ for _, elem := range p.TimeLockedClassItems {
+ _ = elem // Avoid unused variable warning
+ size += 1
+ size += 1
+ // Nested array: StartingItems
+ for _, nestedElem := range elem.StartingItems {
+ _ = nestedElem // Avoid unused variable
+ size += 4
+ size += 1
+ size += 1
+ size += 1
+ size += 4
+ size += 4
+
+ }
+
+ }
+
+ size += 13
+
+ return size
+}
+
+
+
+
+
+
+
+
+
diff --git a/defs/xml/common.xml b/defs/xml/common.xml
index 6ab28aa..3ce92a3 100644
--- a/defs/xml/common.xml
+++ b/defs/xml/common.xml
@@ -1,21 +1,21 @@
-
-
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -41,24 +41,24 @@
-
-
-
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -84,26 +84,26 @@
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
+
@@ -129,25 +129,25 @@
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -173,26 +173,26 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -218,14 +218,14 @@
-
+
-
+
@@ -254,19 +254,19 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -274,7 +274,7 @@
-
+
@@ -300,7 +300,7 @@
-
+
@@ -308,7 +308,7 @@
-
+
@@ -337,19 +337,19 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -357,7 +357,7 @@
-
+
@@ -385,7 +385,7 @@
-
+
@@ -393,7 +393,7 @@
-
+
@@ -422,20 +422,20 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -443,7 +443,7 @@
-
+
@@ -471,7 +471,7 @@
-
+
@@ -479,7 +479,7 @@
-
+
@@ -508,20 +508,20 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
@@ -529,7 +529,7 @@
-
+
@@ -557,7 +557,7 @@
-
+
@@ -565,7 +565,7 @@
-
+
@@ -594,26 +594,26 @@
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -639,14 +639,14 @@
-
+
-
+
@@ -672,30 +672,30 @@
-
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
+
@@ -721,14 +721,14 @@
-
+
-
+
@@ -754,11 +754,11 @@
-
+
-
+
diff --git a/defs/xml/eq2.xml b/defs/xml/eq2.xml
deleted file mode 100644
index 6e7c019..0000000
--- a/defs/xml/eq2.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/defs/xml/login.xml b/defs/xml/login.xml
index 60f5418..3a50cfd 100644
--- a/defs/xml/login.xml
+++ b/defs/xml/login.xml
@@ -52,8 +52,8 @@
-
-
+
+
diff --git a/types/color.go b/types/color.go
new file mode 100644
index 0000000..2d45560
--- /dev/null
+++ b/types/color.go
@@ -0,0 +1,85 @@
+package types
+
+import (
+ "encoding/binary"
+ "io"
+)
+
+// Color represents an RGBA color value
+type Color struct {
+ R uint8
+ G uint8
+ B uint8
+ A uint8
+}
+
+// NewColor creates a new Color from RGBA values
+func NewColor(r, g, b, a uint8) Color {
+ return Color{R: r, G: g, B: b, A: a}
+}
+
+// NewColorFromUint32 creates a Color from a packed uint32 (0xAARRGGBB)
+func NewColorFromUint32(packed uint32) Color {
+ return Color{
+ R: uint8((packed >> 16) & 0xFF),
+ G: uint8((packed >> 8) & 0xFF),
+ B: uint8(packed & 0xFF),
+ A: uint8((packed >> 24) & 0xFF),
+ }
+}
+
+// ToUint32 converts the color to a packed uint32 (0xAARRGGBB)
+func (c Color) ToUint32() uint32 {
+ return uint32(c.A)<<24 | uint32(c.R)<<16 | uint32(c.G)<<8 | uint32(c.B)
+}
+
+// Serialize writes the color as a uint32 to a writer
+func (c Color) Serialize(w io.Writer) error {
+ return binary.Write(w, binary.LittleEndian, c.ToUint32())
+}
+
+// SerializeToBytes writes the color to a byte slice at the given offset
+func (c Color) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint32(dest[*offset:], c.ToUint32())
+ *offset += 4
+}
+
+// Size returns the serialized size of the color (always 4 bytes)
+func (c Color) Size() uint32 {
+ return 4
+}
+
+// Deserialize reads a color from a reader
+func (c *Color) Deserialize(r io.Reader) error {
+ var packed uint32
+ if err := binary.Read(r, binary.LittleEndian, &packed); err != nil {
+ return err
+ }
+ *c = NewColorFromUint32(packed)
+ return nil
+}
+
+// EQ2Color is an alias for Color specifically for EQ2 packets
+// EQ2 sometimes uses different color formats, this allows for customization
+type EQ2Color Color
+
+// Serialize writes the EQ2 color as a uint32 to a writer
+func (c EQ2Color) Serialize(w io.Writer) error {
+ return Color(c).Serialize(w)
+}
+
+// SerializeToBytes writes the EQ2 color to a byte slice
+func (c EQ2Color) SerializeToBytes(dest []byte, offset *uint32) {
+ Color(c).SerializeToBytes(dest, offset)
+}
+
+// Size returns the serialized size (always 4 bytes)
+func (c EQ2Color) Size() uint32 {
+ return 4
+}
+
+// Deserialize reads an EQ2 color from a reader
+func (c *EQ2Color) Deserialize(r io.Reader) error {
+ color := (*Color)(c)
+ return color.Deserialize(r)
+}
\ No newline at end of file
diff --git a/types/equipment.go b/types/equipment.go
new file mode 100644
index 0000000..a5a8606
--- /dev/null
+++ b/types/equipment.go
@@ -0,0 +1,40 @@
+package types
+
+import (
+ "encoding/binary"
+ "io"
+)
+
+// EquipmentItem represents an equipment item with model and color information
+type EquipmentItem struct {
+ Type uint16 // Model/item type ID
+ Color Color // RGB color for the item
+}
+
+// Serialize writes the equipment item to a writer
+func (e *EquipmentItem) Serialize(w io.Writer) error {
+ if err := binary.Write(w, binary.LittleEndian, e.Type); err != nil {
+ return err
+ }
+ return e.Color.Serialize(w)
+}
+
+// SerializeToBytes writes the equipment item to a byte slice at the given offset
+func (e *EquipmentItem) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint16(dest[*offset:], e.Type)
+ *offset += 2
+ e.Color.SerializeToBytes(dest, offset)
+}
+
+// Size returns the serialized size of the equipment item
+func (e *EquipmentItem) Size() uint32 {
+ return 2 + e.Color.Size() // 2 bytes for type + color size
+}
+
+// Deserialize reads an equipment item from a reader
+func (e *EquipmentItem) Deserialize(r io.Reader) error {
+ if err := binary.Read(r, binary.LittleEndian, &e.Type); err != nil {
+ return err
+ }
+ return e.Color.Deserialize(r)
+}
\ No newline at end of file
diff --git a/types/fixed.go b/types/fixed.go
new file mode 100644
index 0000000..30031ff
--- /dev/null
+++ b/types/fixed.go
@@ -0,0 +1,71 @@
+package types
+
+import (
+ "io"
+)
+
+// FixedString represents a fixed-length string field
+type FixedString struct {
+ Data []byte
+ Size int
+}
+
+// NewFixedString creates a new fixed string with the specified size
+func NewFixedString(size int) *FixedString {
+ return &FixedString{
+ Data: make([]byte, size),
+ Size: size,
+ }
+}
+
+// SetString sets the string value, truncating or padding as needed
+func (f *FixedString) SetString(s string) {
+ copy(f.Data, []byte(s))
+ // Pad with zeros if string is shorter than fixed size
+ for i := len(s); i < f.Size; i++ {
+ f.Data[i] = 0
+ }
+}
+
+// String returns the string value, trimming null bytes
+func (f *FixedString) String() string {
+ // Find first null byte
+ for i, b := range f.Data {
+ if b == 0 {
+ return string(f.Data[:i])
+ }
+ }
+ return string(f.Data)
+}
+
+// Serialize writes the fixed string to a writer
+func (f *FixedString) Serialize(w io.Writer) error {
+ _, err := w.Write(f.Data)
+ return err
+}
+
+// SerializeToBytes writes the fixed string to a byte slice
+func (f *FixedString) SerializeToBytes(dest []byte, offset *uint32) {
+ copy(dest[*offset:], f.Data)
+ *offset += uint32(f.Size)
+}
+
+// Deserialize reads a fixed string from a reader
+func (f *FixedString) Deserialize(r io.Reader) error {
+ _, err := io.ReadFull(r, f.Data)
+ return err
+}
+
+// FixedArray represents a fixed-size array of primitive types
+type FixedArray[T any] struct {
+ Data []T
+ Size int
+}
+
+// NewFixedArray creates a new fixed array with the specified size
+func NewFixedArray[T any](size int) *FixedArray[T] {
+ return &FixedArray[T]{
+ Data: make([]T, size),
+ Size: size,
+ }
+}
diff --git a/types/packet.go b/types/packet.go
new file mode 100644
index 0000000..3a5ba3a
--- /dev/null
+++ b/types/packet.go
@@ -0,0 +1,219 @@
+package types
+
+import (
+ "bytes"
+ "encoding/binary"
+ "io"
+)
+
+// Packet represents a basic EQ2 packet interface
+type Packet interface {
+ Serialize(dest []byte) uint32
+ Size() uint32
+}
+
+// PacketWriter helps with writing packet data
+type PacketWriter struct {
+ buffer *bytes.Buffer
+ offset uint32
+}
+
+// NewPacketWriter creates a new packet writer
+func NewPacketWriter() *PacketWriter {
+ return &PacketWriter{
+ buffer: new(bytes.Buffer),
+ offset: 0,
+ }
+}
+
+// WriteUint8 writes a uint8 value
+func (pw *PacketWriter) WriteUint8(v uint8) error {
+ return binary.Write(pw.buffer, binary.LittleEndian, v)
+}
+
+// WriteUint16 writes a uint16 value
+func (pw *PacketWriter) WriteUint16(v uint16) error {
+ return binary.Write(pw.buffer, binary.LittleEndian, v)
+}
+
+// WriteUint32 writes a uint32 value
+func (pw *PacketWriter) WriteUint32(v uint32) error {
+ return binary.Write(pw.buffer, binary.LittleEndian, v)
+}
+
+// WriteUint64 writes a uint64 value
+func (pw *PacketWriter) WriteUint64(v uint64) error {
+ return binary.Write(pw.buffer, binary.LittleEndian, v)
+}
+
+// WriteString8 writes a string with 8-bit length prefix
+func (pw *PacketWriter) WriteString8(s string) error {
+ str := EQ2String8(s)
+ return str.Serialize(pw.buffer)
+}
+
+// WriteString16 writes a string with 16-bit length prefix
+func (pw *PacketWriter) WriteString16(s string) error {
+ str := EQ2String16(s)
+ return str.Serialize(pw.buffer)
+}
+
+// WriteString32 writes a string with 32-bit length prefix
+func (pw *PacketWriter) WriteString32(s string) error {
+ str := EQ2String32(s)
+ return str.Serialize(pw.buffer)
+}
+
+// WriteColor writes a color value
+func (pw *PacketWriter) WriteColor(c Color) error {
+ return c.Serialize(pw.buffer)
+}
+
+// WriteFloat32 writes a float32 value
+func (pw *PacketWriter) WriteFloat32(v float32) error {
+ f := Float32(v)
+ return f.Serialize(pw.buffer)
+}
+
+// WriteFloat64 writes a float64 value
+func (pw *PacketWriter) WriteFloat64(v float64) error {
+ f := Float64(v)
+ return f.Serialize(pw.buffer)
+}
+
+// Bytes returns the written bytes
+func (pw *PacketWriter) Bytes() []byte {
+ return pw.buffer.Bytes()
+}
+
+// Size returns the current size of written data
+func (pw *PacketWriter) Size() uint32 {
+ return uint32(pw.buffer.Len())
+}
+
+// PacketReader helps with reading packet data
+type PacketReader struct {
+ reader io.Reader
+ offset uint32
+}
+
+// NewPacketReader creates a new packet reader
+func NewPacketReader(data []byte) *PacketReader {
+ return &PacketReader{
+ reader: bytes.NewReader(data),
+ offset: 0,
+ }
+}
+
+// NewPacketReaderFromReader creates a packet reader from an io.Reader
+func NewPacketReaderFromReader(r io.Reader) *PacketReader {
+ return &PacketReader{
+ reader: r,
+ offset: 0,
+ }
+}
+
+// ReadUint8 reads a uint8 value
+func (pr *PacketReader) ReadUint8() (uint8, error) {
+ var v uint8
+ err := binary.Read(pr.reader, binary.LittleEndian, &v)
+ if err == nil {
+ pr.offset++
+ }
+ return v, err
+}
+
+// ReadUint16 reads a uint16 value
+func (pr *PacketReader) ReadUint16() (uint16, error) {
+ var v uint16
+ err := binary.Read(pr.reader, binary.LittleEndian, &v)
+ if err == nil {
+ pr.offset += 2
+ }
+ return v, err
+}
+
+// ReadUint32 reads a uint32 value
+func (pr *PacketReader) ReadUint32() (uint32, error) {
+ var v uint32
+ err := binary.Read(pr.reader, binary.LittleEndian, &v)
+ if err == nil {
+ pr.offset += 4
+ }
+ return v, err
+}
+
+// ReadUint64 reads a uint64 value
+func (pr *PacketReader) ReadUint64() (uint64, error) {
+ var v uint64
+ err := binary.Read(pr.reader, binary.LittleEndian, &v)
+ if err == nil {
+ pr.offset += 8
+ }
+ return v, err
+}
+
+// ReadString8 reads a string with 8-bit length prefix
+func (pr *PacketReader) ReadString8() (string, error) {
+ var s EQ2String8
+ err := s.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += s.Size()
+ }
+ return string(s), err
+}
+
+// ReadString16 reads a string with 16-bit length prefix
+func (pr *PacketReader) ReadString16() (string, error) {
+ var s EQ2String16
+ err := s.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += s.Size()
+ }
+ return string(s), err
+}
+
+// ReadString32 reads a string with 32-bit length prefix
+func (pr *PacketReader) ReadString32() (string, error) {
+ var s EQ2String32
+ err := s.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += s.Size()
+ }
+ return string(s), err
+}
+
+// ReadColor reads a color value
+func (pr *PacketReader) ReadColor() (Color, error) {
+ var c Color
+ err := c.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += 4
+ }
+ return c, err
+}
+
+// ReadFloat32 reads a float32 value
+func (pr *PacketReader) ReadFloat32() (float32, error) {
+ var f Float32
+ err := f.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += 4
+ }
+ return float32(f), err
+}
+
+// ReadFloat64 reads a float64 value
+func (pr *PacketReader) ReadFloat64() (float64, error) {
+ var f Float64
+ err := f.Deserialize(pr.reader)
+ if err == nil {
+ pr.offset += 8
+ }
+ return float64(f), err
+}
+
+// Offset returns the current read offset
+func (pr *PacketReader) Offset() uint32 {
+ return pr.offset
+}
\ No newline at end of file
diff --git a/types/primitives.go b/types/primitives.go
new file mode 100644
index 0000000..95fad45
--- /dev/null
+++ b/types/primitives.go
@@ -0,0 +1,81 @@
+package types
+
+import (
+ "encoding/binary"
+ "io"
+ "math"
+)
+
+// Float32 provides serialization methods for float32
+type Float32 float32
+
+func (f Float32) Serialize(w io.Writer) error {
+ return binary.Write(w, binary.LittleEndian, math.Float32bits(float32(f)))
+}
+
+func (f Float32) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint32(dest[*offset:], math.Float32bits(float32(f)))
+ *offset += 4
+}
+
+func (f Float32) Size() uint32 {
+ return 4
+}
+
+func (f *Float32) Deserialize(r io.Reader) error {
+ var bits uint32
+ if err := binary.Read(r, binary.LittleEndian, &bits); err != nil {
+ return err
+ }
+ *f = Float32(math.Float32frombits(bits))
+ return nil
+}
+
+// Float64 provides serialization methods for float64
+type Float64 float64
+
+func (f Float64) Serialize(w io.Writer) error {
+ return binary.Write(w, binary.LittleEndian, math.Float64bits(float64(f)))
+}
+
+func (f Float64) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint64(dest[*offset:], math.Float64bits(float64(f)))
+ *offset += 8
+}
+
+func (f Float64) Size() uint32 {
+ return 8
+}
+
+func (f *Float64) Deserialize(r io.Reader) error {
+ var bits uint64
+ if err := binary.Read(r, binary.LittleEndian, &bits); err != nil {
+ return err
+ }
+ *f = Float64(math.Float64frombits(bits))
+ return nil
+}
+
+// GetTypeSize returns the size in bytes for common EQ2 types
+func GetTypeSize(typeName string) uint32 {
+ switch typeName {
+ case "int8", "uint8", "byte", "char":
+ return 1
+ case "int16", "uint16":
+ return 2
+ case "int32", "uint32", "float", "float32", "color":
+ return 4
+ case "int64", "uint64", "double", "float64":
+ return 8
+ default:
+ return 0
+ }
+}
+
+// Serializable interface for types that can be serialized
+type Serializable interface {
+ Serialize(w io.Writer) error
+ SerializeToBytes(dest []byte, offset *uint32)
+ Size() uint32
+ Deserialize(r io.Reader) error
+}
\ No newline at end of file
diff --git a/types/strings.go b/types/strings.go
new file mode 100644
index 0000000..e07f7df
--- /dev/null
+++ b/types/strings.go
@@ -0,0 +1,151 @@
+package types
+
+import (
+ "encoding/binary"
+ "io"
+)
+
+// EQ2String8 represents a string with an 8-bit length prefix
+type EQ2String8 string
+
+// Serialize writes the string with 8-bit length prefix
+func (s EQ2String8) Serialize(w io.Writer) error {
+ if len(s) > 255 {
+ return io.ErrShortWrite
+ }
+
+ // Write length byte
+ if err := binary.Write(w, binary.LittleEndian, uint8(len(s))); err != nil {
+ return err
+ }
+
+ // Write string data
+ _, err := w.Write([]byte(s))
+ return err
+}
+
+// SerializeToBytes writes the string to a byte slice at the given offset
+func (s EQ2String8) SerializeToBytes(dest []byte, offset *uint32) {
+ dest[*offset] = uint8(len(s))
+ *offset++
+ copy(dest[*offset:], []byte(s))
+ *offset += uint32(len(s))
+}
+
+// Size returns the serialized size (1 byte length + string data)
+func (s EQ2String8) Size() uint32 {
+ return 1 + uint32(len(s))
+}
+
+// Deserialize reads a string with 8-bit length prefix
+func (s *EQ2String8) Deserialize(r io.Reader) error {
+ var length uint8
+ if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
+ return err
+ }
+
+ data := make([]byte, length)
+ if _, err := io.ReadFull(r, data); err != nil {
+ return err
+ }
+
+ *s = EQ2String8(data)
+ return nil
+}
+
+// EQ2String16 represents a string with a 16-bit length prefix
+type EQ2String16 string
+
+// Serialize writes the string with 16-bit length prefix
+func (s EQ2String16) Serialize(w io.Writer) error {
+ if len(s) > 65535 {
+ return io.ErrShortWrite
+ }
+
+ // Write length as uint16
+ if err := binary.Write(w, binary.LittleEndian, uint16(len(s))); err != nil {
+ return err
+ }
+
+ // Write string data
+ _, err := w.Write([]byte(s))
+ return err
+}
+
+// SerializeToBytes writes the string to a byte slice at the given offset
+func (s EQ2String16) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint16(dest[*offset:], uint16(len(s)))
+ *offset += 2
+ copy(dest[*offset:], []byte(s))
+ *offset += uint32(len(s))
+}
+
+// Size returns the serialized size (2 bytes length + string data)
+func (s EQ2String16) Size() uint32 {
+ return 2 + uint32(len(s))
+}
+
+// Deserialize reads a string with 16-bit length prefix
+func (s *EQ2String16) Deserialize(r io.Reader) error {
+ var length uint16
+ if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
+ return err
+ }
+
+ data := make([]byte, length)
+ if _, err := io.ReadFull(r, data); err != nil {
+ return err
+ }
+
+ *s = EQ2String16(data)
+ return nil
+}
+
+// EQ2String32 represents a string with a 32-bit length prefix
+type EQ2String32 string
+
+// Serialize writes the string with 32-bit length prefix
+func (s EQ2String32) Serialize(w io.Writer) error {
+ // Write length as uint32
+ if err := binary.Write(w, binary.LittleEndian, uint32(len(s))); err != nil {
+ return err
+ }
+
+ // Write string data
+ _, err := w.Write([]byte(s))
+ return err
+}
+
+// SerializeToBytes writes the string to a byte slice at the given offset
+func (s EQ2String32) SerializeToBytes(dest []byte, offset *uint32) {
+ binary.LittleEndian.PutUint32(dest[*offset:], uint32(len(s)))
+ *offset += 4
+ copy(dest[*offset:], []byte(s))
+ *offset += uint32(len(s))
+}
+
+// Size returns the serialized size (4 bytes length + string data)
+func (s EQ2String32) Size() uint32 {
+ return 4 + uint32(len(s))
+}
+
+// Deserialize reads a string with 32-bit length prefix
+func (s *EQ2String32) Deserialize(r io.Reader) error {
+ var length uint32
+ if err := binary.Read(r, binary.LittleEndian, &length); err != nil {
+ return err
+ }
+
+ // Sanity check to prevent huge allocations
+ if length > 1024*1024 { // 1MB limit
+ return io.ErrUnexpectedEOF
+ }
+
+ data := make([]byte, length)
+ if _, err := io.ReadFull(r, data); err != nil {
+ return err
+ }
+
+ *s = EQ2String32(data)
+ return nil
+}
\ No newline at end of file