235 lines
6.4 KiB
Go
235 lines
6.4 KiB
Go
package eq2net
|
|
|
|
import (
|
|
"fmt"
|
|
)
|
|
|
|
// LoginEmuOpcode represents emulator opcodes for the login server
|
|
type LoginEmuOpcode uint16
|
|
|
|
// Login server emulator opcodes
|
|
const (
|
|
LOP_Unknown LoginEmuOpcode = iota
|
|
LOP_LoginRequestMsg
|
|
LOP_LoginByNumRequestMsg
|
|
LOP_WSLoginRequestMsg
|
|
LOP_ESLoginRequestMsg
|
|
LOP_LoginReplyMsg
|
|
LOP_WorldListMsg
|
|
LOP_WorldStatusChangeMsg
|
|
LOP_AllWSDescRequestMsg
|
|
LOP_WSStatusReplyMsg
|
|
LOP_AllCharactersDescRequestMsg
|
|
LOP_AllCharactersDescReplyMsg
|
|
LOP_CreateCharacterRequestMsg
|
|
LOP_ReskinCharacterRequestMsg
|
|
LOP_CreateCharacterReplyMsg
|
|
LOP_WSCreateCharacterRequestMsg
|
|
LOP_WSCreateCharacterReplyMsg
|
|
LOP_DeleteCharacterRequestMsg
|
|
LOP_DeleteCharacterReplyMsg
|
|
LOP_PlayCharacterRequestMsg
|
|
LOP_PlayCharacterReplyMsg
|
|
LOP_ServerPlayCharacterRequestMsg
|
|
LOP_ServerPlayCharacterReplyMsg
|
|
LOP_KeymapLoadMsg
|
|
LOP_KeymapNoneMsg
|
|
LOP_KeymapDataMsg
|
|
LOP_KeymapSaveMsg
|
|
LOP_LSCheckAcctLockMsg
|
|
LOP_WSAcctLockStatusMsg
|
|
LOP_LsRequestClientCrashLogMsg
|
|
LOP_LsClientBaselogReplyMsg
|
|
LOP_LsClientCrashlogReplyMsg
|
|
LOP_LsClientAlertlogReplyMsg
|
|
LOP_LsClientVerifylogReplyMsg
|
|
LOP_BadLanguageFilter
|
|
LOP_WSServerLockMsg
|
|
LOP_WSServerHideMsg
|
|
LOP_LSServerLockMsg
|
|
LOP_UpdateCharacterSheetMsg
|
|
LOP_UpdateInventoryMsg
|
|
LOP_MaxLoginOpcode
|
|
)
|
|
|
|
// LoginPacket represents a login server packet
|
|
type LoginPacket struct {
|
|
EQPacket // Embed base packet
|
|
LoginEmuOpcode LoginEmuOpcode // Login server emulator opcode
|
|
}
|
|
|
|
// NewLoginPacket creates a new login server packet
|
|
func NewLoginPacket(opcode LoginEmuOpcode, data []byte) *LoginPacket {
|
|
base := NewEQPacket(uint16(opcode), data)
|
|
base.EmuOpcode = uint16(opcode)
|
|
base.OpcodeSize = 1 // Login server uses 1-byte opcodes
|
|
|
|
p := &LoginPacket{
|
|
EQPacket: *base,
|
|
LoginEmuOpcode: opcode,
|
|
}
|
|
return p
|
|
}
|
|
|
|
// ParseLoginPacket creates a login packet from raw data
|
|
func ParseLoginPacket(data []byte) (*LoginPacket, error) {
|
|
if len(data) < 1 {
|
|
return nil, fmt.Errorf("packet too small for login opcode")
|
|
}
|
|
|
|
// Extract 1-byte opcode
|
|
opcode := LoginEmuOpcode(data[0])
|
|
|
|
// Create packet with remaining data
|
|
base := NewEQPacket(uint16(opcode), data[1:])
|
|
base.EmuOpcode = uint16(opcode)
|
|
base.OpcodeSize = 1
|
|
|
|
p := &LoginPacket{
|
|
EQPacket: *base,
|
|
LoginEmuOpcode: opcode,
|
|
}
|
|
|
|
return p, nil
|
|
}
|
|
|
|
// GetLoginOpcode returns the login emulator opcode
|
|
func (p *LoginPacket) GetLoginOpcode() LoginEmuOpcode {
|
|
return p.LoginEmuOpcode
|
|
}
|
|
|
|
// SetLoginOpcode sets the login emulator opcode
|
|
func (p *LoginPacket) SetLoginOpcode(opcode LoginEmuOpcode) {
|
|
p.LoginEmuOpcode = opcode
|
|
p.EmuOpcode = uint16(opcode)
|
|
p.Opcode = uint16(opcode)
|
|
}
|
|
|
|
// SerializeLogin serializes the login packet with proper encoding
|
|
func (p *LoginPacket) SerializeLogin() []byte {
|
|
// Login packets use 1-byte opcodes
|
|
buf := make([]byte, 1+len(p.Buffer))
|
|
buf[0] = byte(p.LoginEmuOpcode)
|
|
|
|
if len(p.Buffer) > 0 {
|
|
copy(buf[1:], p.Buffer)
|
|
}
|
|
|
|
return buf
|
|
}
|
|
|
|
// GetLoginOpcodeName returns the string name of a login emulator opcode
|
|
func GetLoginOpcodeName(opcode LoginEmuOpcode) string {
|
|
switch opcode {
|
|
case LOP_Unknown:
|
|
return "LOP_Unknown"
|
|
case LOP_LoginRequestMsg:
|
|
return "LOP_LoginRequestMsg"
|
|
case LOP_LoginByNumRequestMsg:
|
|
return "LOP_LoginByNumRequestMsg"
|
|
case LOP_WSLoginRequestMsg:
|
|
return "LOP_WSLoginRequestMsg"
|
|
case LOP_ESLoginRequestMsg:
|
|
return "LOP_ESLoginRequestMsg"
|
|
case LOP_LoginReplyMsg:
|
|
return "LOP_LoginReplyMsg"
|
|
case LOP_WorldListMsg:
|
|
return "LOP_WorldListMsg"
|
|
case LOP_WorldStatusChangeMsg:
|
|
return "LOP_WorldStatusChangeMsg"
|
|
case LOP_AllWSDescRequestMsg:
|
|
return "LOP_AllWSDescRequestMsg"
|
|
case LOP_WSStatusReplyMsg:
|
|
return "LOP_WSStatusReplyMsg"
|
|
case LOP_AllCharactersDescRequestMsg:
|
|
return "LOP_AllCharactersDescRequestMsg"
|
|
case LOP_AllCharactersDescReplyMsg:
|
|
return "LOP_AllCharactersDescReplyMsg"
|
|
case LOP_CreateCharacterRequestMsg:
|
|
return "LOP_CreateCharacterRequestMsg"
|
|
case LOP_ReskinCharacterRequestMsg:
|
|
return "LOP_ReskinCharacterRequestMsg"
|
|
case LOP_CreateCharacterReplyMsg:
|
|
return "LOP_CreateCharacterReplyMsg"
|
|
case LOP_WSCreateCharacterRequestMsg:
|
|
return "LOP_WSCreateCharacterRequestMsg"
|
|
case LOP_WSCreateCharacterReplyMsg:
|
|
return "LOP_WSCreateCharacterReplyMsg"
|
|
case LOP_DeleteCharacterRequestMsg:
|
|
return "LOP_DeleteCharacterRequestMsg"
|
|
case LOP_DeleteCharacterReplyMsg:
|
|
return "LOP_DeleteCharacterReplyMsg"
|
|
case LOP_PlayCharacterRequestMsg:
|
|
return "LOP_PlayCharacterRequestMsg"
|
|
case LOP_PlayCharacterReplyMsg:
|
|
return "LOP_PlayCharacterReplyMsg"
|
|
case LOP_ServerPlayCharacterRequestMsg:
|
|
return "LOP_ServerPlayCharacterRequestMsg"
|
|
case LOP_ServerPlayCharacterReplyMsg:
|
|
return "LOP_ServerPlayCharacterReplyMsg"
|
|
case LOP_KeymapLoadMsg:
|
|
return "LOP_KeymapLoadMsg"
|
|
case LOP_KeymapNoneMsg:
|
|
return "LOP_KeymapNoneMsg"
|
|
case LOP_KeymapDataMsg:
|
|
return "LOP_KeymapDataMsg"
|
|
case LOP_KeymapSaveMsg:
|
|
return "LOP_KeymapSaveMsg"
|
|
case LOP_LSCheckAcctLockMsg:
|
|
return "LOP_LSCheckAcctLockMsg"
|
|
case LOP_WSAcctLockStatusMsg:
|
|
return "LOP_WSAcctLockStatusMsg"
|
|
case LOP_LsRequestClientCrashLogMsg:
|
|
return "LOP_LsRequestClientCrashLogMsg"
|
|
case LOP_LsClientBaselogReplyMsg:
|
|
return "LOP_LsClientBaselogReplyMsg"
|
|
case LOP_LsClientCrashlogReplyMsg:
|
|
return "LOP_LsClientCrashlogReplyMsg"
|
|
case LOP_LsClientAlertlogReplyMsg:
|
|
return "LOP_LsClientAlertlogReplyMsg"
|
|
case LOP_LsClientVerifylogReplyMsg:
|
|
return "LOP_LsClientVerifylogReplyMsg"
|
|
case LOP_BadLanguageFilter:
|
|
return "LOP_BadLanguageFilter"
|
|
case LOP_WSServerLockMsg:
|
|
return "LOP_WSServerLockMsg"
|
|
case LOP_WSServerHideMsg:
|
|
return "LOP_WSServerHideMsg"
|
|
case LOP_LSServerLockMsg:
|
|
return "LOP_LSServerLockMsg"
|
|
case LOP_UpdateCharacterSheetMsg:
|
|
return "LOP_UpdateCharacterSheetMsg"
|
|
case LOP_UpdateInventoryMsg:
|
|
return "LOP_UpdateInventoryMsg"
|
|
default:
|
|
return fmt.Sprintf("Unknown(%d)", opcode)
|
|
}
|
|
}
|
|
|
|
// ConvertToProtocolPacket wraps this login packet in a protocol packet
|
|
func (p *LoginPacket) ConvertToProtocolPacket() *ProtocolPacket {
|
|
// Serialize the login packet
|
|
loginData := p.SerializeLogin()
|
|
|
|
// Create protocol packet with OP_Packet opcode
|
|
proto := NewProtocolPacket(OP_Packet, loginData)
|
|
|
|
// Copy network info
|
|
proto.SrcIP = p.SrcIP
|
|
proto.SrcPort = p.SrcPort
|
|
proto.DstIP = p.DstIP
|
|
proto.DstPort = p.DstPort
|
|
proto.Timestamp = p.Timestamp
|
|
proto.Version = p.Version
|
|
|
|
return proto
|
|
}
|
|
|
|
// Copy creates a deep copy of the login packet
|
|
func (p *LoginPacket) Copy() *LoginPacket {
|
|
newPacket := &LoginPacket{
|
|
EQPacket: *p.Clone(),
|
|
LoginEmuOpcode: p.LoginEmuOpcode,
|
|
}
|
|
return newPacket
|
|
} |