1
0

fill out readme

This commit is contained in:
Sky Johnson 2025-09-05 18:42:57 -05:00
parent 6d57815a14
commit c5d5998c8a

333
README.md
View File

@ -2,4 +2,335 @@
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.
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.