# EQ2 Protocol

This library is meant to replicate EverQuest 2's UDP protocol. The work here is based on the immense
work done by contributors to the EQ2Emu project. I am porting it to Go with the idea of a simpler, faster
development pipeline - and as a personal experiment.

## Opcodes

The opcodes package manages the mapping between internal emulator opcodes and client-specific opcodes across different client versions.

### OpcodeManager

The `OpcodeManager` handles opcode translation for specific client versions:

```go
import "git.sharkk.net/EQ2/Protocol/opcodes"

// Create a manager for client version 60085
om := opcodes.NewOpcodeManager(60085)

// Load opcode mappings from database
err := om.LoadFromDatabase(db, "opcodes_table")

// Convert between emulator and client opcodes
clientOpcode := om.EmuToEQ(opcodes.OP_LoginRequestMsg)
emuOpcode := om.EQToEmu(0x0123)

// Get opcode names
name := om.EmuToName(opcodes.OP_LoginRequestMsg)
```

### Opcode Types

- **EmuOpcode**: Internal emulator opcodes (constants like `OP_LoginRequestMsg`)
- **Protocol opcodes**: Low-level protocol opcodes (e.g., `OP_SessionRequest`, `OP_Packet`)
- **Client opcodes**: Version-specific opcodes sent to/from the game client

### Global Manager Cache

```go
// Get or create a manager for a specific version
mgr := opcodes.GetManager(version, db, tableName)

// Get all loaded versions
versions := opcodes.GetLoadedVersions()
```

## Packet Definitions

The defs package provides structured packet definitions with automatic version selection based on client version.

### PacketManager

Manages packet structure lookups with version-aware selection:

```go
import "git.sharkk.net/EQ2/Protocol/defs"

// Create a manager for client version 60085
pm := defs.NewPacketManager(60085)

// Get the appropriate packet struct for this version
ps := pm.GetStruct("CreateCharacter", 60085)
// Returns CreateCharacterV60085 struct

// Get by exact version
ps := pm.GetStructByVersion("CreateCharacter", 373)

// Get by opcode
ps := pm.GetStructByOpcode(opcodes.OP_CreateCharacterRequestMsg)

// Create a new packet instance
packet := pm.CreateInstance("CreateCharacter")
```

### Version Selection

The manager automatically selects the highest packet version that doesn't exceed the client version:

- Client 1000 requesting "CreateCharacter" gets version 869
- Client 60085 requesting "CreateCharacter" gets version 60085
- Client 70000 requesting "CreateCharacter" gets version 65534

### Code Generation

Packet structures and registrations are generated from XML definitions:

```bash
# Regenerate packet structures from XML
cd defs && go generate

# XML definitions are in defs/xml/
# Generated code goes to defs/generated/
```

## Packets

The packets package provides base packet types and interfaces for all protocol packets.

### Packet Interface

All packets implement the `Packet` interface:

```go
type Packet interface {
    GetOpcode() uint16
    SetOpcode(uint16)
    GetVersion() uint16
    SetVersion(uint16)
    GetSequence() uint16
    SetSequence(uint16)
    GetData() []byte
    GetSize() uint32
}
```

### Base Packet Types

```go
// RawPacket - Basic packet with opcode and data
packet := &packets.RawPacket{
    Opcode: 0x0123,
    Data:   []byte{...},
}

// EncodedPacket - Packet with protocol encoding
encoded := &packets.EncodedPacket{
    Sequence:   seq,
    Opcode:     opcode,
    Data:       data,
    Compressed: false,
}
```

### Packet Processing

```go
// Check if packet needs processing
if packet.ShouldCombine() {
    // Handle combined packets
}

if packet.IsProtocolPacket() {
    // Handle protocol-level packets
}

// Encode for transmission
encoded := packet.Encode()

// Decode received data
packet, err := packets.Decode(data)
```

## Stream

The stream package handles bidirectional packet streaming with buffering, fragmentation, and reassembly.

### PacketStream

Manages packet flow between client and server:

```go
import "git.sharkk.net/EQ2/Protocol/stream"

// Create a new packet stream
stream := stream.NewPacketStream(conn, bufferSize)

// Set packet handlers
stream.SetIncomingHandler(func(packet packets.Packet) {
    // Process incoming packets
})

stream.SetOutgoingHandler(func(packet packets.Packet) {
    // Process outgoing packets
})

// Start processing
stream.Start()

// Send a packet
err := stream.Send(packet)

// Receive packets (handled by callback)
// Packets are automatically decoded and reassembled
```

### Features

- **Automatic fragmentation**: Large packets are split into fragments
- **Reassembly**: Fragments are automatically reassembled
- **Buffering**: Configurable send/receive buffers
- **Sequencing**: Automatic sequence number management
- **Compression**: Optional packet compression support

### Stream Configuration

```go
config := &stream.Config{
    MaxPacketSize:    512,
    BufferSize:       8192,
    EnableCompression: true,
    Timeout:          30 * time.Second,
}

stream := stream.NewPacketStreamWithConfig(conn, config)
```

## Factory

The factory package provides centralized packet creation and registration.

### PacketFactory

Creates packets based on opcodes and manages packet type registration:

```go
import "git.sharkk.net/EQ2/Protocol/factory"

// Get the global factory instance
factory := factory.GetInstance()

// Register a packet type
factory.RegisterPacket(opcodes.OP_LoginRequestMsg, func() packets.Packet {
    return &LoginRequestPacket{}
})

// Create a packet by opcode
packet := factory.CreatePacket(opcodes.OP_LoginRequestMsg)

// Create with data
packet := factory.CreatePacketWithData(opcode, data)

// Create from raw bytes (auto-detects type)
packet, err := factory.CreateFromBytes(rawData)
```

### Packet Registration

Packets can be registered globally or per-version:

```go
// Register for all versions
factory.RegisterPacket(opcode, constructor)

// Register version-specific
factory.RegisterVersionedPacket(opcode, version, constructor)

// Bulk registration
factory.RegisterPackets(map[uint16]PacketConstructor{
    opcodes.OP_LoginRequestMsg: NewLoginRequest,
    opcodes.OP_CharacterCreate: NewCharacterCreate,
})
```

### Integration with PacketManager

The factory can work with the defs package for automatic struct-based packets:

```go
// Set packet manager for automatic struct registration
factory.SetPacketManager(defs.GetManager(version))

// Now factory can create packets from struct definitions
packet := factory.CreatePacket(opcodes.OP_CreateCharacterRequestMsg)
// Returns properly versioned CreateCharacter struct
```

## Usage Example

Complete example showing protocol usage:

```go
package main

import (
    "git.sharkk.net/EQ2/Protocol/opcodes"
    "git.sharkk.net/EQ2/Protocol/defs"
    "git.sharkk.net/EQ2/Protocol/stream"
    "git.sharkk.net/EQ2/Protocol/factory"
)

func main() {
    version := uint16(60085)
    
    // Initialize managers
    opcodeManager := opcodes.GetManager(version, db, "opcodes")
    packetManager := defs.GetManager(version)
    
    // Setup factory
    factory := factory.GetInstance()
    factory.SetPacketManager(packetManager)
    
    // Create stream for connection
    stream := stream.NewPacketStream(conn, 8192)
    
    // Handle incoming packets
    stream.SetIncomingHandler(func(packet packets.Packet) {
        // Translate opcode
        emuOpcode := opcodeManager.EQToEmu(packet.GetOpcode())
        
        // Process based on opcode
        switch emuOpcode {
        case opcodes.OP_LoginRequestMsg:
            handleLogin(packet)
        case opcodes.OP_CreateCharacterRequestMsg:
            handleCharacterCreate(packet)
        }
    })
    
    // Send a packet
    packet := packetManager.CreateInstance("LSWorldList")
    populateWorldList(packet)
    
    // Convert to client opcode
    clientOpcode := opcodeManager.EmuToEQ(opcodes.OP_WorldListMsg)
    packet.SetOpcode(clientOpcode)
    
    // Send to client
    stream.Send(packet)
    
    // Start processing
    stream.Start()
}
```

## Protocol Architecture

The protocol library is organized in layers:

1. **Opcodes**: Manages opcode mappings and translations
2. **Defs**: Defines packet structures with version management
3. **Packets**: Base packet types and interfaces
4. **Factory**: Creates packet instances from opcodes/data
5. **Stream**: Handles network I/O, fragmentation, and reassembly

Each layer builds on the previous, providing a complete protocol implementation for EQ2 server emulation.