266 lines
7.8 KiB
Markdown
266 lines
7.8 KiB
Markdown
# Housing Package
|
|
|
|
The housing package provides a complete housing system for EverQuest II servers, allowing players to purchase, manage, and customize their in-game homes.
|
|
|
|
## Overview
|
|
|
|
This package implements a streamlined housing system with three core components:
|
|
- **House**: Represents purchasable house types/zones with costs and requirements
|
|
- **CharacterHouse**: Represents houses owned by specific characters
|
|
- **HousingManager**: Orchestrates all housing operations including purchases, upkeep, and packet communication
|
|
|
|
## Features
|
|
|
|
### House Management
|
|
- Multiple house types with different costs, requirements, and features
|
|
- Alignment and guild level restrictions
|
|
- Vault storage slots and exit coordinates
|
|
- Configurable costs in coins and status points
|
|
|
|
### Character Houses
|
|
- Individual house ownership tracking
|
|
- Upkeep payment system with automatic processing
|
|
- House settings (name, visit permissions, notes)
|
|
- Access control lists for other players
|
|
- Item placement and management
|
|
- Transaction history tracking
|
|
|
|
### System Features
|
|
- Automatic upkeep processing with configurable grace periods
|
|
- Foreclosure system for unpaid upkeep
|
|
- Maximum house limits per player
|
|
- Integrated packet building for client communication
|
|
- Database persistence with MySQL support
|
|
- Comprehensive logging and error handling
|
|
|
|
## Usage
|
|
|
|
### Basic Setup
|
|
|
|
```go
|
|
import "eq2emu/internal/housing"
|
|
|
|
// Create housing manager
|
|
logger := &MyLogger{} // Implement housing.Logger interface
|
|
config := housing.HousingConfig{
|
|
EnableUpkeep: true,
|
|
EnableForeclosure: true,
|
|
UpkeepGracePeriod: 7 * 24 * 3600, // 7 days in seconds
|
|
MaxHousesPerPlayer: 10,
|
|
EnableStatistics: true,
|
|
}
|
|
|
|
hm := housing.NewHousingManager(db, logger, config)
|
|
|
|
// Initialize and load house data
|
|
ctx := context.Background()
|
|
if err := hm.Initialize(ctx); err != nil {
|
|
log.Fatal("Failed to initialize housing:", err)
|
|
}
|
|
```
|
|
|
|
### House Purchase Flow
|
|
|
|
```go
|
|
// Player wants to purchase house type 1
|
|
playerManager := &MyPlayerManager{} // Implement housing.PlayerManager interface
|
|
characterID := int32(12345)
|
|
houseTypeID := int32(1)
|
|
|
|
house, err := hm.PurchaseHouse(ctx, characterID, houseTypeID, playerManager)
|
|
if err != nil {
|
|
// Handle purchase error (insufficient funds, requirements not met, etc.)
|
|
return err
|
|
}
|
|
|
|
// House purchased successfully
|
|
fmt.Printf("Player %d purchased house %s", characterID, house.Settings.HouseName)
|
|
```
|
|
|
|
### Upkeep Management
|
|
|
|
```go
|
|
// Pay upkeep for a specific house
|
|
houseUniqueID := int64(98765)
|
|
err := hm.PayUpkeep(ctx, houseUniqueID, playerManager)
|
|
if err != nil {
|
|
// Handle upkeep payment error
|
|
return err
|
|
}
|
|
|
|
// Automatic upkeep processing runs in background
|
|
// No manual intervention needed
|
|
```
|
|
|
|
### Packet Communication
|
|
|
|
```go
|
|
// Send house purchase UI to client
|
|
house, exists := hm.GetHouse(houseTypeID)
|
|
if exists {
|
|
err := hm.SendHousePurchasePacket(characterID, clientVersion, house)
|
|
// Packet sent to client
|
|
}
|
|
|
|
// Send player's house list to client
|
|
err := hm.SendCharacterHousesPacket(characterID, clientVersion)
|
|
// Housing list packet sent to client
|
|
```
|
|
|
|
## Architecture
|
|
|
|
### Core Types
|
|
|
|
- **House**: Static house type definitions loaded from database
|
|
- **CharacterHouse**: Player-owned house instances with settings and history
|
|
- **HousingManager**: Central coordinator for all housing operations
|
|
|
|
### Database Integration
|
|
|
|
The housing system integrates with MySQL databases using the centralized database package:
|
|
|
|
```sql
|
|
-- House type definitions
|
|
character_house_zones (id, name, cost_coins, cost_status, ...)
|
|
|
|
-- Player house instances
|
|
character_houses (unique_id, char_id, house_id, upkeep_due, ...)
|
|
```
|
|
|
|
### Packet Integration
|
|
|
|
Integrates with the centralized packet system using XML-driven packet definitions:
|
|
- Uses `packets.GetPacket()` to load packet definitions
|
|
- Builds packets with `packets.NewPacketBuilder()`
|
|
- Supports multiple client versions automatically
|
|
|
|
## Configuration
|
|
|
|
### HousingConfig Options
|
|
|
|
- `EnableUpkeep`: Enable automatic upkeep processing
|
|
- `EnableForeclosure`: Allow foreclosure of houses with overdue upkeep
|
|
- `UpkeepGracePeriod`: Grace period in seconds before foreclosure
|
|
- `MaxHousesPerPlayer`: Maximum houses per character
|
|
- `EnableStatistics`: Enable housing statistics tracking
|
|
|
|
### House Types
|
|
|
|
House types are configured in the database with these properties:
|
|
- **Cost**: Coin and status point requirements
|
|
- **Upkeep**: Weekly maintenance costs
|
|
- **Alignment**: Good/Evil/Neutral/Any restrictions
|
|
- **Guild Level**: Minimum guild level required
|
|
- **Vault Slots**: Number of storage slots provided
|
|
- **Zone Info**: Location and exit coordinates
|
|
|
|
## Constants
|
|
|
|
The package provides extensive constants for:
|
|
- **House Types**: Cottage, Mansion, Keep, etc.
|
|
- **Access Levels**: Owner, Friend, Visitor, Guild Member
|
|
- **Transaction Types**: Purchase, Upkeep, Deposit, etc.
|
|
- **Permission Flags**: Enter, Place Items, Vault Access, etc.
|
|
- **Status Codes**: Active, Upkeep Due, Foreclosed, etc.
|
|
|
|
See `constants.go` for complete listings and default values.
|
|
|
|
## Interfaces
|
|
|
|
### Logger Interface
|
|
|
|
Implement this interface to provide logging:
|
|
|
|
```go
|
|
type Logger interface {
|
|
LogInfo(system, format string, args ...interface{})
|
|
LogError(system, format string, args ...interface{})
|
|
LogDebug(system, format string, args ...interface{})
|
|
LogWarning(system, format string, args ...interface{})
|
|
}
|
|
```
|
|
|
|
### PlayerManager Interface
|
|
|
|
Implement this interface to integrate with player systems:
|
|
|
|
```go
|
|
type PlayerManager interface {
|
|
CanPlayerAffordHouse(characterID int32, coinCost, statusCost int64) (bool, error)
|
|
DeductPlayerCoins(characterID int32, amount int64) error
|
|
DeductPlayerStatus(characterID int32, amount int64) error
|
|
GetPlayerAlignment(characterID int32) (int8, error)
|
|
GetPlayerGuildLevel(characterID int32) (int8, error)
|
|
}
|
|
```
|
|
|
|
## Utility Functions
|
|
|
|
### Currency Formatting
|
|
|
|
```go
|
|
housing.FormatCurrency(15250) // Returns "1g 52s 50c"
|
|
housing.FormatCurrency(1000) // Returns "10s"
|
|
housing.FormatCurrency(50) // Returns "50c"
|
|
```
|
|
|
|
### Upkeep Date Formatting
|
|
|
|
```go
|
|
housing.FormatUpkeepDue(time.Now().Add(24 * time.Hour)) // "Due in 1 days"
|
|
housing.FormatUpkeepDue(time.Now().Add(-24 * time.Hour)) // "Overdue (1 days)"
|
|
```
|
|
|
|
## Testing
|
|
|
|
The package includes comprehensive tests with mock implementations:
|
|
|
|
```bash
|
|
go test ./internal/housing/ -v
|
|
```
|
|
|
|
Tests cover:
|
|
- House and CharacterHouse creation
|
|
- Purchase validation (funds, alignment, guild level)
|
|
- Upkeep processing and foreclosure
|
|
- Packet building integration
|
|
- Currency and date formatting
|
|
- Full system integration scenarios
|
|
|
|
## Error Handling
|
|
|
|
The housing system provides detailed error codes and messages:
|
|
|
|
- `HouseErrorInsufficientFunds`: Player cannot afford purchase/upkeep
|
|
- `HouseErrorAlignmentRestriction`: Player alignment doesn't meet requirements
|
|
- `HouseErrorGuildLevelRestriction`: Player guild level too low
|
|
- `HouseErrorMaxHousesReached`: Player at house limit
|
|
- `HouseErrorHouseNotFound`: Invalid house type requested
|
|
|
|
See `constants.go` for complete error code definitions.
|
|
|
|
## Performance
|
|
|
|
The housing system is designed for efficiency:
|
|
- **In-Memory Caching**: House types and character houses cached in memory
|
|
- **Lazy Loading**: Character houses loaded on first access
|
|
- **Background Processing**: Upkeep processing runs asynchronously
|
|
- **Optimized Queries**: Direct SQL queries without ORM overhead
|
|
- **Minimal Allocations**: Reuses data structures where possible
|
|
|
|
## Thread Safety
|
|
|
|
All housing operations are thread-safe:
|
|
- `sync.RWMutex` protects shared data structures
|
|
- Database operations use connection pooling
|
|
- Concurrent access to houses is properly synchronized
|
|
|
|
## Future Enhancements
|
|
|
|
Potential areas for extension:
|
|
- House decoration and furniture systems
|
|
- Guild halls with special permissions
|
|
- Real estate marketplace for player trading
|
|
- Rental system for temporary housing
|
|
- Advanced statistics and reporting
|
|
- Integration with crafting systems |