144 lines
3.6 KiB
Go
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)
|
|
}
|