# EverQuest II Zone System

This package implements a comprehensive zone management system for the EverQuest II server emulator, converted from the original C++ implementation while leveraging Go's concurrency and type safety features.

## Overview

The zone system handles:
- **Zone Management**: Loading, initialization, and lifecycle management of game zones
- **Instance Management**: Creating and managing instanced zones for groups, raids, and solo play
- **Spawn Management**: NPCs, objects, widgets, signs, and ground spawns with spatial optimization
- **Movement System**: NPC movement with pathfinding, stuck detection, and multiple movement modes
- **Position System**: 3D position calculations, distance functions, and EQ2-specific heading math
- **Weather System**: Dynamic weather with patterns, severity controls, and client synchronization
- **Database Integration**: Persistent storage of zone configuration, spawns, and player data
- **Client Management**: Player connections, spawn visibility, and packet communication
- **Grid System**: Spatial partitioning for efficient range queries and spawn management

## Architecture

### Core Components

#### ZoneServer (`zone_server.go`)
- Central coordinator for all zone functionality
- Manages clients, spawns, timers, and processing loops
- Handles zone initialization, configuration, and shutdown
- Thread-safe operations using sync.RWMutex and atomic values
- Supports both regular zones and instances

#### ZoneManager (`zone_manager.go`)
- High-level management of multiple zones and instances
- Automatic loading/unloading based on demand
- Instance creation with type-specific player limits
- Statistics collection and monitoring
- Cleanup of inactive instances

#### MobMovementManager (`movement_manager.go`)
- Advanced NPC movement system with command queuing
- Pathfinding integration with multiple backends
- Stuck detection and recovery mechanisms
- Multiple movement modes (walk, run, swim, fly)
- Thread-safe processing with delta time calculations

#### Position System (`position.go`)
- EverQuest II specific 3D math utilities
- Distance calculations (2D, 3D, 4D with heading)
- Heading conversion and normalization (512-unit circle)
- Bounding box and cylinder collision detection
- Interpolation and random position generation

#### Database Layer (`database.go`)
- Complete zone data persistence with prepared statements
- Transaction support for atomic updates
- Efficient loading of zone configuration and spawn data
- Support for spawn locations, groups, and associations
- Thread-safe operations with connection pooling

### Key Features

#### Spatial Optimization
- **Grid System**: Spatial partitioning for efficient spawn queries
- **Range-based Updates**: Only process spawns within client visibility
- **Distance Culling**: Automatic spawn loading/unloading based on distance
- **Grid-based Indexing**: Fast lookup of nearby spawns and objects

#### Instance System
- **Multiple Instance Types**: Group, raid, solo, tradeskill, housing, quest instances
- **Automatic Limits**: Type-specific player count restrictions
- **Lifecycle Management**: Automatic creation and cleanup
- **Persistence Options**: Lockout vs persistent instances

#### Movement System
- **Command Queuing**: Sequential movement command execution
- **Pathfinding Integration**: Multiple pathfinding backends (navmesh, waypoint, null)
- **Stuck Detection**: Position-based stuck detection with recovery strategies
- **Smooth Movement**: Delta-time based position interpolation
- **Multi-mode Support**: Walking, running, swimming, flying

#### Weather System
- **Dynamic Patterns**: Normal, dynamic, random, and chaotic weather types
- **Severity Control**: Min/max bounds with configurable change rates
- **Pattern Support**: Increasing, decreasing, and random severity patterns
- **Client Synchronization**: Automatic weather updates to all clients

## Usage Examples

### Basic Zone Creation and Management

```go
// Create zone server
zoneServer := NewZoneServer("qeynos")

// Configure zone
config := &ZoneServerConfig{
    ZoneName:          "qeynos",
    ZoneFile:          "qeynos.zone",
    ZoneDescription:   "Qeynos: Capitol of Antonica",
    ZoneID:            100,
    InstanceID:        0,
    InstanceType:      InstanceTypeNone,
    MaxPlayers:        200,
    MinLevel:          1,
    MaxLevel:          100,
    SafeX:             830.0,
    SafeY:             -25.0,
    SafeZ:             -394.0,
    SafeHeading:       0.0,
    LoadMaps:          true,
    EnableWeather:     true,
    EnablePathfinding: true,
}

// Initialize zone
err := zoneServer.Initialize(config)
if err != nil {
    log.Fatal(err)
}

// Add client to zone
err = zoneServer.AddClient(client)
if err != nil {
    log.Printf("Failed to add client: %v", err)
}
```

### Zone Manager Usage

```go
// Create zone manager
config := &ZoneManagerConfig{
    MaxZones:            50,
    MaxInstanceZones:    500,
    ProcessInterval:     time.Millisecond * 100,
    CleanupInterval:     time.Minute * 5,
    EnableWeather:       true,
    EnablePathfinding:   true,
}

zoneManager := NewZoneManager(config, database)

// Start zone manager
err := zoneManager.Start()
if err != nil {
    log.Fatal(err)
}

// Load a zone
zone, err := zoneManager.LoadZone(100) // Qeynos
if err != nil {
    log.Printf("Failed to load zone: %v", err)
}

// Create an instance
instance, err := zoneManager.CreateInstance(100, InstanceTypeGroupLockout, playerID)
if err != nil {
    log.Printf("Failed to create instance: %v", err)
}
```

### Movement System Usage

```go
// Get movement manager from zone
movementMgr := zoneServer.movementMgr

// Add NPC to movement tracking
spawnID := int32(1001)
movementMgr.AddMovementSpawn(spawnID)

// Command NPC to move
err := movementMgr.MoveTo(spawnID, 100.0, 200.0, 0.0, DefaultRunSpeed)
if err != nil {
    log.Printf("Movement command failed: %v", err)
}

// Queue multiple commands
movementMgr.MoveTo(spawnID, 150.0, 250.0, 0.0, DefaultWalkSpeed)
movementMgr.RotateTo(spawnID, 256.0, 90.0) // Turn around
movementMgr.MoveTo(spawnID, 100.0, 200.0, 0.0, DefaultRunSpeed) // Return

// Check if moving
if movementMgr.IsMoving(spawnID) {
    state := movementMgr.GetMovementState(spawnID)
    log.Printf("NPC %d is moving at speed %.2f", spawnID, state.Speed)
}
```

### Position Calculations

```go
// Calculate distance between two points
distance := Distance3D(0, 0, 0, 100, 100, 100)
log.Printf("Distance: %.2f", distance)

// Calculate heading from one point to another
heading := CalculateHeading(0, 0, 100, 100)
log.Printf("Heading: %.2f", heading)

// Work with positions
pos1 := NewPosition(10.0, 20.0, 30.0, 128.0)
pos2 := NewPosition(50.0, 60.0, 30.0, 256.0)

distance = pos1.DistanceTo3D(pos2)
log.Printf("Position distance: %.2f", distance)

// Check if positions are within range
if IsWithinRange(pos1, pos2, 100.0) {
    log.Println("Positions are within range")
}

// Create bounding box and test containment
bbox := NewBoundingBox(0, 0, 0, 100, 100, 100)
if bbox.ContainsPosition(pos1) {
    log.Println("Position is inside bounding box")
}
```

### Weather System

```go
// Set rain level
zoneServer.SetRain(0.8) // Heavy rain

// Weather is processed automatically, but can be triggered manually
zoneServer.ProcessWeather()

// Configure weather (typically done during initialization)
zoneServer.weatherEnabled = true
zoneServer.weatherType = WeatherTypeDynamic
zoneServer.weatherFrequency = 600 // 10 minutes
zoneServer.weatherMinSeverity = 0.0
zoneServer.weatherMaxSeverity = 1.0
zoneServer.weatherChangeAmount = 0.1
zoneServer.weatherChangeChance = 75 // 75% chance of change
```

## Database Schema

The zone system uses several database tables:

### Core Zone Configuration
```sql
CREATE TABLE zones (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    file TEXT,
    description TEXT,
    safe_x REAL DEFAULT 0,
    safe_y REAL DEFAULT 0,
    safe_z REAL DEFAULT 0,
    safe_heading REAL DEFAULT 0,
    underworld REAL DEFAULT -1000,
    min_level INTEGER DEFAULT 0,
    max_level INTEGER DEFAULT 0,
    max_players INTEGER DEFAULT 100,
    instance_type INTEGER DEFAULT 0,
    expansion_flag INTEGER DEFAULT 0,
    weather_allowed INTEGER DEFAULT 1,
    -- ... additional fields
);
```

### Spawn Locations
```sql
CREATE TABLE spawn_location_placement (
    id INTEGER PRIMARY KEY,
    zone_id INTEGER,
    x REAL,
    y REAL,
    z REAL,
    heading REAL,
    spawn_type INTEGER,
    respawn_time INTEGER DEFAULT 600,
    conditions INTEGER DEFAULT 0,
    spawn_percentage REAL DEFAULT 100.0
);
```

### Spawn Groups
```sql
CREATE TABLE spawn_location_group (
    group_id INTEGER,
    location_id INTEGER,
    zone_id INTEGER
);
```

## Configuration

### Key Constants

- **Distance Constants**: `SendSpawnDistance` (250), `RemoveSpawnDistance` (300)
- **Movement Speeds**: `DefaultWalkSpeed` (2.5), `DefaultRunSpeed` (7.0)
- **Timer Intervals**: Configurable processing intervals for different systems
- **Capacity Limits**: `MaxSpawnsPerGrid` (100), `MaxClientsPerZone` (200)

### Zone Rules

Zones can be configured with various rules:
- Player level restrictions (min/max)
- Client version requirements
- PvP enablement
- Weather settings
- Instance type and capacity
- Expansion and holiday flags

## Thread Safety

All zone operations are designed to be thread-safe:
- **RWMutex Usage**: Separate read/write locks for different data structures
- **Atomic Operations**: For simple flags and counters
- **Channel Communication**: For cross-goroutine messaging
- **Immutable Data**: Where possible, data structures are immutable
- **Copy-on-Read**: Returns copies of data to prevent race conditions

## Performance Considerations

- **Spatial Indexing**: Grid-based partitioning reduces O(n) to O(1) for range queries
- **Prepared Statements**: All database queries use prepared statements
- **Object Pooling**: Reuse of frequently allocated objects
- **Lazy Loading**: Zone data loaded on demand
- **Concurrent Processing**: Multiple goroutines for different subsystems
- **Memory Management**: Regular cleanup of expired objects and timers

## Error Handling

The zone system provides comprehensive error handling:
- **Graceful Degradation**: Systems continue operating when non-critical components fail
- **Detailed Logging**: All errors logged with appropriate prefixes and context
- **Recovery Mechanisms**: Automatic recovery from common error conditions
- **Validation**: Input validation at all API boundaries
- **Timeouts**: All operations have appropriate timeouts

## Testing

Comprehensive test suite includes:
- Unit tests for all major components
- Integration tests for database operations
- Performance benchmarks for critical paths
- Mock implementations for testing isolation
- Property-based testing for mathematical functions

Run tests with:
```bash
go test ./internal/zone/...
go test -race ./internal/zone/...  # Race condition detection
go test -bench=. ./internal/zone/  # Performance benchmarks
```

## Migration from C++

This Go implementation maintains compatibility with the original C++ EQ2EMu zone system:

- **Database Schema**: Identical table structure and relationships
- **Protocol Compatibility**: Same client communication protocols
- **Algorithmic Equivalence**: Math functions produce identical results
- **Configuration Format**: Compatible configuration files and settings
- **Performance**: Comparable or improved performance through Go's concurrency

## Dependencies

- **Standard Library**: sync, time, database/sql, math
- **Internal Packages**: database, spawn, common
- **External**: SQLite driver (zombiezen.com/go/sqlite)

## Future Enhancements

Planned improvements include:
- **Advanced Pathfinding**: Integration with Detour navigation mesh
- **Lua Scripting**: Full Lua integration for spawn behaviors
- **Physics Engine**: Advanced collision detection and physics
- **Clustering**: Multi-server zone distribution
- **Hot Reloading**: Dynamic configuration updates without restart