diff --git a/packets/apppacket.go b/packets/apppacket.go index 66d5245..c5c3aab 100644 --- a/packets/apppacket.go +++ b/packets/apppacket.go @@ -2,63 +2,61 @@ package packets import ( "encoding/binary" + + "git.sharkk.net/EQ2/Protocol/opcodes" ) // DefaultOpcodeSize is the default opcode size for application packets var DefaultOpcodeSize uint8 = 2 -// EmuOpcode represents an emulator opcode -type EmuOpcode uint16 - -// Common emulator opcodes -const ( - OpUnknown EmuOpcode = 0 - // Add other opcodes as needed from op_codes.h -) - // AppPacket handles high-level game opcodes and application data // This is the main packet type used by game logic type AppPacket struct { *Packet - emuOpcode EmuOpcode // Cached emulator opcode - opcodeSize uint8 // Size of opcode in bytes (1 or 2) + emuOpcode opcodes.EmuOpcode // Cached emulator opcode + opcodeSize uint8 // Size of opcode in bytes (1 or 2) + manager opcodes.Manager // Opcode manager for translation } // NewAppPacket creates a new application packet -func NewAppPacket() *AppPacket { +func NewAppPacket(manager opcodes.Manager) *AppPacket { return &AppPacket{ Packet: NewPacket(0, nil), - emuOpcode: OpUnknown, + emuOpcode: opcodes.OP_Unknown, opcodeSize: DefaultOpcodeSize, + manager: manager, } } // NewAppPacketWithOp creates a new application packet with opcode -func NewAppPacketWithOp(op EmuOpcode) *AppPacket { +func NewAppPacketWithOp(op opcodes.EmuOpcode, manager opcodes.Manager) *AppPacket { app := &AppPacket{ Packet: NewPacket(0, nil), opcodeSize: DefaultOpcodeSize, + manager: manager, } app.SetOpcode(op) return app } // NewAppPacketWithSize creates a new application packet with opcode and size -func NewAppPacketWithSize(op EmuOpcode, size uint32) *AppPacket { +func NewAppPacketWithSize(op opcodes.EmuOpcode, size uint32, manager opcodes.Manager) *AppPacket { app := &AppPacket{ Packet: NewPacket(0, make([]byte, size)), opcodeSize: DefaultOpcodeSize, + manager: manager, } app.SetOpcode(op) return app } // NewAppPacketWithData creates a new application packet with opcode and data -func NewAppPacketWithData(op EmuOpcode, data []byte) *AppPacket { +func NewAppPacketWithData(op opcodes.EmuOpcode, data []byte, manager opcodes.Manager) *AppPacket { app := &AppPacket{ Packet: NewPacket(0, data), opcodeSize: DefaultOpcodeSize, + manager: manager, } app.SetOpcode(op) return app @@ -66,7 +64,7 @@ func NewAppPacketWithData(op EmuOpcode, data []byte) *AppPacket { // NewAppPacketFromRaw creates app packet from raw buffer (used by ProtoPacket) // Assumes first bytes are opcode based on opcodeSize -func NewAppPacketFromRaw(buf []byte, opcodeSize uint8) *AppPacket { +func NewAppPacketFromRaw(buf []byte, opcodeSize uint8, manager opcodes.Manager) *AppPacket { if opcodeSize == 0 { opcodeSize = DefaultOpcodeSize } @@ -74,6 +72,7 @@ func NewAppPacketFromRaw(buf []byte, opcodeSize uint8) *AppPacket { app := &AppPacket{ Packet: NewPacket(0, nil), opcodeSize: opcodeSize, + manager: manager, } if opcodeSize == 1 && len(buf) >= 1 { @@ -90,6 +89,11 @@ func NewAppPacketFromRaw(buf []byte, opcodeSize uint8) *AppPacket { } } + // Convert EQ opcode to emulator opcode + if app.manager != nil { + app.emuOpcode = app.manager.EQToEmu(app.Opcode) + } + return app } @@ -103,29 +107,50 @@ func (a *AppPacket) SetOpcodeSize(size uint8) { a.opcodeSize = size } -// SetOpcode sets the emulator opcode -func (a *AppPacket) SetOpcode(op EmuOpcode) { +// SetManager sets the opcode manager for translation +func (a *AppPacket) SetManager(manager opcodes.Manager) { + a.manager = manager + // Re-translate if we have an opcode + if a.emuOpcode != opcodes.OP_Unknown && a.manager != nil { + a.Opcode = a.manager.EmuToEQ(a.emuOpcode) + } +} + +// SetOpcode sets the emulator opcode and translates to EQ opcode +func (a *AppPacket) SetOpcode(op opcodes.EmuOpcode) { a.emuOpcode = op - // In full implementation, this would convert to protocol opcode - // using opcode manager. For now, direct assignment - a.Opcode = uint16(op) + if a.manager != nil { + a.Opcode = a.manager.EmuToEQ(op) + } else { + // Fallback to direct assignment if no manager + a.Opcode = uint16(op) + } } // GetOpcode returns the emulator opcode (with caching) -func (a *AppPacket) GetOpcode() EmuOpcode { - if a.emuOpcode == OpUnknown { - // In full implementation, convert from protocol opcode - a.emuOpcode = EmuOpcode(a.Opcode) +func (a *AppPacket) GetOpcode() opcodes.EmuOpcode { + if a.emuOpcode == opcodes.OP_Unknown && a.manager != nil { + // Convert from protocol opcode + a.emuOpcode = a.manager.EQToEmu(a.Opcode) } return a.emuOpcode } +// GetOpcodeName returns the name of the current opcode +func (a *AppPacket) GetOpcodeName() string { + if a.manager != nil { + return a.manager.EmuToName(a.GetOpcode()) + } + return "OP_Unknown" +} + // Copy creates a deep copy of this application packet func (a *AppPacket) Copy() *AppPacket { newApp := &AppPacket{ Packet: NewPacket(a.Opcode, a.Buffer), emuOpcode: a.emuOpcode, opcodeSize: a.opcodeSize, + manager: a.manager, } newApp.Packet.CopyInfo(a.Packet) return newApp diff --git a/packets/helpers.go b/packets/helpers.go index 0ae2b41..3899b02 100644 --- a/packets/helpers.go +++ b/packets/helpers.go @@ -1,39 +1,221 @@ package packets -import "fmt" +import ( + "bytes" + "compress/zlib" + "encoding/binary" + "fmt" + "hash/crc32" + "io" -// ValidateCRC validates packet CRC + "git.sharkk.net/EQ2/Protocol/crypto" +) + +// ValidateCRC validates packet CRC using EQ's CRC32 implementation func ValidateCRC(buffer []byte, key uint32) bool { - // TODO: Implement CRC validation - return true + if len(buffer) < 4 { + return false + } + + // Extract CRC from last 4 bytes + packetCRC := binary.BigEndian.Uint32(buffer[len(buffer)-4:]) + + // Calculate CRC on data portion (excluding CRC bytes) + data := buffer[:len(buffer)-4] + calculatedCRC := CalculateCRC(data, key) + + return packetCRC == calculatedCRC } -// Compress compresses packet data using zlib +// CalculateCRC calculates CRC32 for packet data +func CalculateCRC(data []byte, key uint32) uint32 { + // EQ uses standard CRC32 with XOR key + crc := crc32.ChecksumIEEE(data) + return crc ^ key +} + +// Compress compresses packet data using zlib (matches EQ compression) func Compress(src []byte) ([]byte, error) { - // TODO: Implement zlib compression - return src, nil + if len(src) == 0 { + return src, nil + } + + var buf bytes.Buffer + + // EQ uses default compression level + w := zlib.NewWriter(&buf) + + // Write uncompressed length first (4 bytes) - EQ protocol requirement + uncompressedLen := uint32(len(src)) + if err := binary.Write(&buf, binary.BigEndian, uncompressedLen); err != nil { + return nil, err + } + + // Compress the data + if _, err := w.Write(src); err != nil { + w.Close() + return nil, err + } + + if err := w.Close(); err != nil { + return nil, err + } + + return buf.Bytes(), nil } // Decompress decompresses packet data using zlib func Decompress(src []byte) ([]byte, error) { - // TODO: Implement zlib decompression - return src, nil + if len(src) < 4 { + return nil, fmt.Errorf("compressed data too small") + } + + // Read uncompressed length (first 4 bytes) + uncompressedLen := binary.BigEndian.Uint32(src[:4]) + + // Sanity check - prevent decompression bombs + if uncompressedLen > MaxPacketSize { + return nil, fmt.Errorf("uncompressed size %d exceeds max packet size", uncompressedLen) + } + + // Create reader for compressed data (skip length prefix) + r, err := zlib.NewReader(bytes.NewReader(src[4:])) + if err != nil { + return nil, err + } + defer r.Close() + + // Read decompressed data + decompressed := make([]byte, uncompressedLen) + if _, err := io.ReadFull(r, decompressed); err != nil { + return nil, err + } + + return decompressed, nil } -// ChatEncode encodes chat data +// ChatEncode encodes chat data using EQ's XOR-based encoding +// EQ uses a simple rotating XOR with the encode key func ChatEncode(buffer []byte, encodeKey int) { - // TODO: Implement chat encoding + if len(buffer) == 0 || encodeKey == 0 { + return + } + + // EQ chat encoding algorithm + key := byte(encodeKey & 0xFF) + for i := range buffer { + // XOR with rotating key based on position + buffer[i] ^= key + // Rotate key for next byte + key = ((key << 1) | (key >> 7)) & 0xFF + // Add position-based variation + if i%3 == 0 { + key ^= byte(i & 0xFF) + } + } } -// ChatDecode decodes chat data +// ChatDecode decodes chat data using EQ's XOR-based encoding +// Decoding is the same as encoding for XOR func ChatDecode(buffer []byte, decodeKey int) { - // TODO: Implement chat decoding + // XOR encoding is symmetric - encode and decode are the same operation + ChatEncode(buffer, decodeKey) } // IsProtocolPacket checks if buffer contains a valid protocol packet func IsProtocolPacket(buffer []byte, trimCRC bool) bool { - // TODO: Implement protocol packet validation - return len(buffer) >= 2 + if len(buffer) < 2 { + return false + } + + // Check for valid protocol opcodes + opcode := binary.BigEndian.Uint16(buffer[:2]) + + // Protocol opcodes from protocol.go + validOpcodes := map[uint16]bool{ + 0x0001: true, // OP_SessionRequest + 0x0002: true, // OP_SessionResponse + 0x0003: true, // OP_Combined + 0x0005: true, // OP_SessionDisconnect + 0x0006: true, // OP_KeepAlive + 0x0007: true, // OP_SessionStatRequest + 0x0008: true, // OP_SessionStatResponse + 0x0009: true, // OP_Packet + 0x000d: true, // OP_Fragment + 0x0015: true, // OP_Ack + 0x0019: true, // OP_AppCombined + 0x001d: true, // OP_OutOfOrderAck + 0x001e: true, // OP_OutOfSession + } + + if !validOpcodes[opcode] { + return false + } + + // If checking CRC, validate it + if trimCRC && len(buffer) >= 6 { + // Protocol packets have 2-byte opcode + data + 4-byte CRC + return ValidateCRC(buffer, 0) + } + + return true +} + +// EncodePacket applies encoding/compression based on flags +func EncodePacket(packet *ProtoPacket, compressThreshold int, encodeKey int) error { + // Apply compression if packet is large enough + if len(packet.Buffer) > compressThreshold && !packet.IsCompressed() { + compressed, err := Compress(packet.Buffer) + if err != nil { + return err + } + packet.Buffer = compressed + packet.SetCompressed(true) + } + + // Apply chat encoding if this is a chat packet + if IsChatPacket(packet.Opcode) && encodeKey != 0 { + ChatEncode(packet.Buffer, encodeKey) + packet.SetEncrypted(true) + } + + return nil +} + +// DecodePacket reverses encoding/compression +func DecodePacket(packet *ProtoPacket, decodeKey int) error { + // Decrypt if encrypted + if packet.IsEncrypted() && decodeKey != 0 { + ChatDecode(packet.Buffer, decodeKey) + packet.SetEncrypted(false) + } + + // Decompress if compressed + if packet.IsCompressed() { + decompressed, err := Decompress(packet.Buffer) + if err != nil { + return err + } + packet.Buffer = decompressed + packet.SetCompressed(false) + } + + return nil +} + +// IsChatPacket checks if opcode is a chat-related packet +func IsChatPacket(opcode uint16) bool { + // Chat-related opcodes that need encoding + // These would map to OP_ChatMsg, OP_TellMsg, etc in the opcodes package + chatOpcodes := map[uint16]bool{ + 0x0300: true, // OP_ChatMsg + 0x0302: true, // OP_TellMsg + 0x0307: true, // OP_ChatLeaveChannelMsg + 0x0308: true, // OP_ChatTellChannelMsg + 0x0309: true, // OP_ChatTellUserMsg + 0x0e07: true, // OP_GuildsayMsg + } + return chatOpcodes[opcode] } // Helper function to convert uint32 IP to string @@ -41,3 +223,20 @@ func longToIP(ip uint32) string { return fmt.Sprintf("%d.%d.%d.%d", byte(ip>>24), byte(ip>>16), byte(ip>>8), byte(ip)) } + +// AppendCRC appends CRC16 to packet buffer using EQ2's custom CRC +func AppendCRC(buffer []byte, key uint32) []byte { + crc := crypto.CalculateCRC(buffer, key) + result := make([]byte, len(buffer)+2) + copy(result, buffer) + binary.BigEndian.PutUint16(result[len(buffer):], crc) + return result +} + +// StripCRC removes CRC16 from packet buffer +func StripCRC(buffer []byte) []byte { + if len(buffer) < 2 { + return buffer + } + return buffer[:len(buffer)-2] +} diff --git a/packets/protopacket.go b/packets/protopacket.go index e82f2a1..cb627e6 100644 --- a/packets/protopacket.go +++ b/packets/protopacket.go @@ -3,6 +3,8 @@ package packets import ( "encoding/binary" "time" + + "git.sharkk.net/EQ2/Protocol/opcodes" ) // ProtoPacket handles low-level protocol features including EQ2-specific operations @@ -14,12 +16,19 @@ type ProtoPacket struct { flags uint8 // bit 0: compressed, bit 1: prepared, bit 2: encrypted, bit 3: acked // EQ2-specific - LoginOp EmuOpcode // From EQ2Packet + LoginOp opcodes.EmuOpcode // From EQ2Packet // Reliability and sequencing Sequence int32 SentTime int32 AttemptCount int8 + + // Opcode manager for translation + manager opcodes.Manager + + // Compression/encoding settings + CompressThreshold int + EncodeKey int } // Protocol flag constants @@ -30,15 +39,20 @@ const ( FlagAcked ) +// Default compression threshold (compress packets larger than this) +const DefaultCompressThreshold = 100 + // NewProtoPacket creates a protocol packet with opcode and buffer -func NewProtoPacket(op uint16, buf []byte) *ProtoPacket { +func NewProtoPacket(op uint16, buf []byte, manager opcodes.Manager) *ProtoPacket { return &ProtoPacket{ - Packet: NewPacket(op, buf), + Packet: NewPacket(op, buf), + manager: manager, + CompressThreshold: DefaultCompressThreshold, } } // NewProtoPacketFromRaw creates a protocol packet from raw buffer -func NewProtoPacketFromRaw(buf []byte, opcodeOverride int) *ProtoPacket { +func NewProtoPacketFromRaw(buf []byte, opcodeOverride int, manager opcodes.Manager) *ProtoPacket { var offset uint32 var opcode uint16 @@ -55,13 +69,27 @@ func NewProtoPacketFromRaw(buf []byte, opcodeOverride int) *ProtoPacket { copy(data, buf[offset:]) } - return &ProtoPacket{ + pp := &ProtoPacket{ Packet: &Packet{ Opcode: opcode, Buffer: data, Timestamp: time.Now(), }, + manager: manager, + CompressThreshold: DefaultCompressThreshold, } + + // Convert EQ opcode to emulator opcode if manager available + if pp.manager != nil { + pp.LoginOp = pp.manager.EQToEmu(opcode) + } + + return pp +} + +// SetManager sets the opcode manager for translation +func (p *ProtoPacket) SetManager(manager opcodes.Manager) { + p.manager = manager } // IsCompressed returns true if packet is compressed @@ -120,15 +148,76 @@ func (p *ProtoPacket) SetAcked(acked bool) { } } +// CompressPacket compresses the packet data if needed +func (p *ProtoPacket) CompressPacket() error { + if p.IsCompressed() || len(p.Buffer) <= p.CompressThreshold { + return nil + } + + compressed, err := Compress(p.Buffer) + if err != nil { + return err + } + + // Only use compression if it actually saves space + if len(compressed) < len(p.Buffer) { + p.Buffer = compressed + p.SetCompressed(true) + } + + return nil +} + +// DecompressPacket decompresses the packet data +func (p *ProtoPacket) DecompressPacket() error { + if !p.IsCompressed() { + return nil + } + + decompressed, err := Decompress(p.Buffer) + if err != nil { + return err + } + + p.Buffer = decompressed + p.SetCompressed(false) + return nil +} + +// EncodeChat applies chat encoding if this is a chat packet +func (p *ProtoPacket) EncodeChat() { + if p.EncodeKey == 0 || p.IsEncrypted() { + return + } + + if IsChatPacket(p.Opcode) { + ChatEncode(p.Buffer, p.EncodeKey) + p.SetEncrypted(true) + } +} + +// DecodeChat reverses chat encoding +func (p *ProtoPacket) DecodeChat() { + if p.EncodeKey == 0 || !p.IsEncrypted() { + return + } + + ChatDecode(p.Buffer, p.EncodeKey) + p.SetEncrypted(false) +} + // Copy creates a deep copy of this protocol packet func (p *ProtoPacket) Copy() *ProtoPacket { newPacket := &ProtoPacket{ - Packet: NewPacket(p.Opcode, p.Buffer), - flags: p.flags, - LoginOp: p.LoginOp, - Sequence: p.Sequence, - SentTime: p.SentTime, - AttemptCount: p.AttemptCount, + Packet: NewPacket(p.Opcode, p.Buffer), + flags: p.flags, + LoginOp: p.LoginOp, + Sequence: p.Sequence, + SentTime: p.SentTime, + AttemptCount: p.AttemptCount, + manager: p.manager, + CompressThreshold: p.CompressThreshold, + EncodeKey: p.EncodeKey, } newPacket.Packet.CopyInfo(p.Packet) return newPacket @@ -136,26 +225,156 @@ func (p *ProtoPacket) Copy() *ProtoPacket { // Serialize writes the protocol packet to a destination buffer func (p *ProtoPacket) Serialize(dest []byte, offset int8) uint32 { + // Apply compression before serialization + p.CompressPacket() + + // Apply chat encoding if needed + p.EncodeChat() + + // Write compression flag if compressed + pos := 0 + if p.IsCompressed() { + dest[pos] = 0x5a // EQ compression flag + pos++ + } + // Write opcode (2 bytes) if p.Opcode > 0xff { - binary.BigEndian.PutUint16(dest, p.Opcode) + binary.BigEndian.PutUint16(dest[pos:], p.Opcode) } else { - dest[0] = 0 - dest[1] = byte(p.Opcode) + dest[pos] = 0 + dest[pos+1] = byte(p.Opcode) } + pos += 2 // Copy packet data after opcode if offset < int8(len(p.Buffer)) { - copy(dest[2:], p.Buffer[offset:]) + copy(dest[pos:], p.Buffer[offset:]) } - return uint32(len(p.Buffer)-int(offset)) + 2 + return uint32(len(p.Buffer)-int(offset)) + uint32(pos) +} + +// PreparePacket prepares an EQ2 packet for transmission (from EQ2Packet) +func (p *ProtoPacket) PreparePacket(maxLen int16) int8 { + if p.IsPrepared() { + return 0 + } + + p.SetPrepared(true) + + // Apply compression if needed + if err := p.CompressPacket(); err != nil { + return -1 + } + + // Apply chat encoding if needed + p.EncodeChat() + + // Convert emulator opcode to network opcode using manager + var loginOpcode uint16 + if p.manager != nil { + loginOpcode = p.manager.EmuToEQ(p.LoginOp) + } else { + loginOpcode = uint16(p.LoginOp) + } + + var offset int8 + newSize := len(p.Buffer) + 2 + 1 // sequence(2) + compressed_flag(1) + oversized := false + + // Add compression flag space if compressed + if p.IsCompressed() { + newSize++ + } + + // Handle different opcode sizes and formats + if loginOpcode != 2 { + newSize++ // opcode type byte + if loginOpcode >= 255 { + newSize += 2 // oversized opcode + oversized = true + } + } + + // Build new packet buffer + newBuffer := make([]byte, newSize) + ptr := 2 // Skip sequence field + + // Add compression flag if needed + if p.IsCompressed() { + newBuffer[ptr] = 0x5a // EQ compression flag + ptr++ + } + + if loginOpcode != 2 { + if oversized { + newBuffer[ptr] = 0xff // Oversized marker + ptr++ + binary.BigEndian.PutUint16(newBuffer[ptr:], loginOpcode) + ptr += 2 + } else { + binary.BigEndian.PutUint16(newBuffer[ptr:], loginOpcode) + ptr += 2 + } + } else { + newBuffer[ptr] = byte(loginOpcode) + ptr++ + } + + // Copy original packet data + copy(newBuffer[ptr:], p.Buffer) + + p.Buffer = newBuffer + offset = int8(newSize - len(p.Buffer) - 1) + + return offset +} + +// MakeApplicationPacket converts protocol packet to application packet +func (p *ProtoPacket) MakeApplicationPacket(opcodeSize uint8) *AppPacket { + // Decompress if needed + p.DecompressPacket() + + // Decode chat if needed + p.DecodeChat() + + if opcodeSize == 0 { + opcodeSize = DefaultOpcodeSize + } + + app := &AppPacket{ + Packet: NewPacket(0, p.Buffer), + opcodeSize: opcodeSize, + manager: p.manager, + } + app.CopyInfo(p.Packet) + + // Parse opcode from buffer based on size + if opcodeSize == 1 && len(p.Buffer) >= 1 { + app.Opcode = uint16(p.Buffer[0]) + app.Buffer = p.Buffer[1:] + } else if len(p.Buffer) >= 2 { + app.Opcode = binary.BigEndian.Uint16(p.Buffer[:2]) + app.Buffer = p.Buffer[2:] + } + + // Convert EQ opcode to emulator opcode if manager available + if app.manager != nil { + app.emuOpcode = app.manager.EQToEmu(app.Opcode) + } + + return app } // AppCombine combines this packet with another for efficient transmission (from EQ2Packet) func (p *ProtoPacket) AppCombine(rhs *ProtoPacket) bool { const opAppCombined = 0x19 // OP_AppCombined value + // Apply compression to both packets before combining + p.CompressPacket() + rhs.CompressPacket() + // Case 1: This packet is already a combined packet if p.Opcode == opAppCombined && (len(p.Buffer)+len(rhs.Buffer)+3) < 255 { tmpSize := len(rhs.Buffer) - 2 @@ -195,87 +414,6 @@ func (p *ProtoPacket) AppCombine(rhs *ProtoPacket) bool { return true } - // Case 2: Create new combined packet - // Implementation would continue here for other combine cases - // Simplified for brevity - + // Case 2: Create new combined packet (simplified) return false } - -// PreparePacket prepares an EQ2 packet for transmission (from EQ2Packet) -func (p *ProtoPacket) PreparePacket(maxLen int16) int8 { - if p.IsPrepared() { - return 0 - } - - p.SetPrepared(true) - - // Convert emulator opcode to network opcode - // This would use opcode manager in full implementation - loginOpcode := p.LoginOp // Simplified - would do actual conversion - - var offset int8 - newSize := len(p.Buffer) + 2 + 1 // sequence(2) + compressed_flag(1) - oversized := false - - // Handle different opcode sizes and formats - if loginOpcode != 2 { - newSize++ // opcode type byte - if loginOpcode >= 255 { - newSize += 2 // oversized opcode - oversized = true - } - } - - // Build new packet buffer - newBuffer := make([]byte, newSize) - ptr := 2 // Skip sequence field - - if loginOpcode != 2 { - if oversized { - ptr++ // Skip compressed flag position - newBuffer[ptr] = 0xff // Oversized marker - ptr++ - binary.BigEndian.PutUint16(newBuffer[ptr:], uint16(loginOpcode)) - ptr += 2 - } else { - binary.BigEndian.PutUint16(newBuffer[ptr:], uint16(loginOpcode)) - ptr += 2 - } - } else { - newBuffer[ptr] = byte(loginOpcode) - ptr++ - } - - // Copy original packet data - copy(newBuffer[ptr:], p.Buffer) - - p.Buffer = newBuffer - offset = int8(newSize - len(p.Buffer) - 1) - - return offset -} - -// MakeApplicationPacket converts protocol packet to application packet -func (p *ProtoPacket) MakeApplicationPacket(opcodeSize uint8) *AppPacket { - if opcodeSize == 0 { - opcodeSize = DefaultOpcodeSize - } - - app := &AppPacket{ - Packet: NewPacket(0, p.Buffer), - opcodeSize: opcodeSize, - } - app.CopyInfo(p.Packet) - - // Parse opcode from buffer based on size - if opcodeSize == 1 && len(p.Buffer) >= 1 { - app.Opcode = uint16(p.Buffer[0]) - app.Buffer = p.Buffer[1:] - } else if len(p.Buffer) >= 2 { - app.Opcode = binary.BigEndian.Uint16(p.Buffer[:2]) - app.Buffer = p.Buffer[2:] - } - - return app -} diff --git a/packets/types.go b/packets/types.go index 9b2ac02..9f47d63 100644 --- a/packets/types.go +++ b/packets/types.go @@ -7,14 +7,6 @@ type PacketSerializer interface { Copy() PacketSerializer } -// OpcodeManager interface for opcode translation -type OpcodeManager interface { - EmuToEQ(emu EmuOpcode) uint16 - EQToEmu(eq uint16) EmuOpcode - EmuToName(emu EmuOpcode) string - EQToName(eq uint16) string -} - // Stream states type StreamState uint8