1
0
EQ2Emu/cmd/loginServer/opcodes.go
2025-07-02 13:14:42 -05:00

144 lines
3.6 KiB
Go

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