package udp import ( "bytes" "compress/zlib" "io" ) // Compression markers used by EQ2EMu protocol const ( CompressedMarker = 0x5A // Marks zlib compressed data UncompressedMarker = 0xA5 // Marks uncompressed data ) // Compress applies zlib compression with EQ2EMu protocol markers // Returns compressed data only if compression provides space savings func Compress(data []byte) ([]byte, error) { // Empty data gets uncompressed marker if len(data) == 0 { return []byte{UncompressedMarker}, nil } var buf bytes.Buffer buf.WriteByte(CompressedMarker) // Compress data using zlib writer := zlib.NewWriter(&buf) if _, err := writer.Write(data); err != nil { return nil, err } if err := writer.Close(); err != nil { return nil, err } // Only use compression if it actually saves space if buf.Len() >= len(data)+1 { result := make([]byte, len(data)+1) result[0] = UncompressedMarker copy(result[1:], data) return result, nil } return buf.Bytes(), nil } // Decompress handles both compressed and uncompressed data based on markers func Decompress(data []byte) ([]byte, error) { if len(data) == 0 { return data, nil } switch data[0] { case UncompressedMarker: // Data is uncompressed - return without marker return data[1:], nil case CompressedMarker: // Data is zlib compressed return decompressZlib(data[1:]) default: // No compression marker - return as-is return data, nil } } // decompressZlib handles zlib decompression func decompressZlib(data []byte) ([]byte, error) { if len(data) == 0 { return nil, io.ErrUnexpectedEOF } reader := bytes.NewReader(data) zlibReader, err := zlib.NewReader(reader) if err != nil { return nil, err } defer zlibReader.Close() var buf bytes.Buffer if _, err := io.Copy(&buf, zlibReader); err != nil { return nil, err } return buf.Bytes(), nil } // IsCompressed checks if data has compression marker func IsCompressed(data []byte) bool { return len(data) > 0 && data[0] == CompressedMarker } // IsUncompressed checks if data has uncompressed marker func IsUncompressed(data []byte) bool { return len(data) > 0 && data[0] == UncompressedMarker } // HasCompressionMarker checks if data has any compression marker func HasCompressionMarker(data []byte) bool { return IsCompressed(data) || IsUncompressed(data) }