1
0
Protocol/login_packet.go
2025-09-02 20:25:42 -05:00

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
}