package main import ( "crypto/rand" "encoding/hex" "errors" ) // Opcodes const ( OpLoginRequest uint16 = 0x0001 OpLoginReply uint16 = 0x0002 OpWorldListRequest uint16 = 0x0003 OpWorldListReply uint16 = 0x0004 OpCharacterListRequest uint16 = 0x0005 OpCharacterListReply uint16 = 0x0006 OpCreateCharacter uint16 = 0x0007 OpCreateCharacterReply uint16 = 0x0008 OpDeleteCharacter uint16 = 0x0009 OpDeleteCharacterReply uint16 = 0x000A OpPlayCharacter uint16 = 0x000B OpPlayCharacterReply uint16 = 0x000C OpError uint16 = 0xFFFF ) var ErrIncompletePacket = errors.New("incomplete packet") type EQ2Packet struct { Opcode uint16 Size uint16 Data []byte } type LoginRequest struct { Username string `json:"username"` Password string `json:"password"` Version int16 `json:"version"` } type LoginResponse struct { Response uint8 `json:"response"` AccountID uint32 `json:"account_id"` SubLevel uint32 `json:"sub_level"` RaceFlag uint32 `json:"race_flag"` ClassFlag uint32 `json:"class_flag"` Username string `json:"username"` Unknown5 uint32 `json:"unknown5"` CitiesFlag uint8 `json:"cities_flag"` Reason string `json:"reason,omitempty"` } type WorldInfo struct { ID uint32 `json:"id"` Name string `json:"name"` Status uint8 `json:"status"` Players uint32 `json:"players"` MaxPlayers uint32 `json:"max_players"` Address string `json:"address"` Port uint16 `json:"port"` Locked bool `json:"locked"` } type WorldListResponse struct { NumWorlds uint32 `json:"num_worlds"` Worlds []*WorldInfo `json:"worlds"` } type Character struct { ID uint32 `json:"id"` Name string `json:"name"` Race uint8 `json:"race"` Class uint8 `json:"class"` Gender uint8 `json:"gender"` Level uint8 `json:"level"` Zone string `json:"zone"` ServerID uint32 `json:"server_id"` Created int64 `json:"created"` LastLogin int64 `json:"last_login"` } type CharacterListResponse struct { NumCharacters uint32 `json:"num_characters"` Characters []*Character `json:"characters"` AccountID uint32 `json:"account_id"` MaxChars uint32 `json:"max_chars"` } type CreateCharacterRequest struct { Name string `json:"name"` Race uint8 `json:"race"` Class uint8 `json:"class"` Gender uint8 `json:"gender"` Deity uint8 `json:"deity"` BodySize float32 `json:"body_size"` BodyAge float32 `json:"body_age"` ServerID uint32 `json:"server_id"` } type CreateCharacterResponse struct { Success bool `json:"success"` CharacterID uint32 `json:"character_id"` Name string `json:"name"` Error string `json:"error,omitempty"` } type DeleteCharacterRequest struct { CharacterID uint32 `json:"character_id"` ServerID uint32 `json:"server_id"` } type DeleteCharacterResponse struct { Success bool `json:"success"` CharacterID uint32 `json:"character_id"` Error string `json:"error,omitempty"` } type PlayCharacterRequest struct { CharacterID uint32 `json:"character_id"` ServerID uint32 `json:"server_id"` } type PlayCharacterResponse struct { Success bool `json:"success"` ServerIP string `json:"server_ip"` ServerPort uint16 `json:"server_port"` SessionKey string `json:"session_key"` Error string `json:"error,omitempty"` } type OpcodeManager struct { opcodes map[string]uint16 } func (om *OpcodeManager) GetOpcode(name string) (uint16, bool) { opcode, exists := om.opcodes[name] return opcode, exists } func generateSessionKey() string { bytes := make([]byte, 16) rand.Read(bytes) return hex.EncodeToString(bytes) }