416 lines
9.6 KiB
Go

/*
Package control is the active record implementation for game control settings.
The control package manages global game configuration settings stored in a single database record (ID 1). Unlike other packages, this one focuses on updating the existing control record rather than creating new ones, as there is only ever one set of game control settings.
# Basic Usage
To retrieve the main control settings:
settings, err := control.Get(db)
if err != nil {
log.Fatal(err)
}
fmt.Printf("World size: %d, Game open: %v\n", settings.WorldSize, settings.IsOpen())
To find control settings by ID (typically always 1):
settings, err := control.Find(db, 1)
if err != nil {
log.Fatal(err)
}
# Updating Settings
Control settings can be modified and saved back to the database:
settings, _ := control.Get(db)
settings.WorldSize = 500
settings.SetOpen(false)
settings.AdminEmail = "newadmin@game.com"
err := settings.Save()
if err != nil {
log.Fatal(err)
}
# Database Schema
The control table has the following structure:
CREATE TABLE control (
id INTEGER PRIMARY KEY AUTOINCREMENT,
world_size INTEGER NOT NULL DEFAULT 250,
open INTEGER NOT NULL DEFAULT 1,
admin_email TEXT NOT NULL DEFAULT '',
class_1_name TEXT NOT NULL DEFAULT '',
class_2_name TEXT NOT NULL DEFAULT '',
class_3_name TEXT NOT NULL DEFAULT ''
)
Where:
- id: Unique identifier (typically always 1)
- world_size: The size of the game world (used for coordinate bounds)
- open: Whether the game is open for new player registration (1=open, 0=closed)
- admin_email: Administrator email address for notifications
- class_1_name, class_2_name, class_3_name: Names of the three player classes
# Game World Management
## World Size and Boundaries
The world size determines the coordinate boundaries for the game:
settings, _ := control.Get(db)
// Get world size and radius
fmt.Printf("World size: %d\n", settings.WorldSize)
fmt.Printf("World radius: %d\n", settings.GetWorldRadius())
// Check coordinate boundaries
minX, minY, maxX, maxY := settings.GetWorldBounds()
fmt.Printf("World bounds: (%d,%d) to (%d,%d)\n", minX, minY, maxX, maxY)
// Validate coordinates
if settings.IsWithinWorldBounds(playerX, playerY) {
fmt.Println("Player is within world boundaries")
}
The world is centered at (0,0) with coordinates ranging from -radius to +radius.
## World Size Validation
Ensure world size settings are reasonable:
settings, _ := control.Get(db)
if !settings.IsWorldSizeValid() {
fmt.Println("Warning: World size is invalid (must be 1-10000)")
settings.WorldSize = 250 // Reset to default
settings.Save()
}
# Player Registration Control
## Managing Game Access
Control whether new players can register:
settings, _ := control.Get(db)
// Check current status
if settings.IsOpen() {
fmt.Println("Game is open for new players")
} else {
fmt.Println("Game is closed to new players")
}
// Change registration status
settings.SetOpen(false) // Close registration
settings.Close() // Alternative method
settings.OpenWorld() // Reopen registration
settings.Save()
## Maintenance Mode
Temporarily close the game for maintenance:
func enterMaintenanceMode(db *database.DB) error {
settings, err := control.Get(db)
if err != nil {
return err
}
settings.Close()
return settings.Save()
}
func exitMaintenanceMode(db *database.DB) error {
settings, err := control.Get(db)
if err != nil {
return err
}
settings.OpenWorld()
return settings.Save()
}
# Player Class Management
## Class Configuration
Manage the three player classes available in the game:
settings, _ := control.Get(db)
// Get all configured class names
classes := settings.GetClassNames()
fmt.Printf("Available classes: %v\n", classes)
// Get specific class name
mageClass := settings.GetClassName(1)
fmt.Printf("Class 1: %s\n", mageClass)
// Set all class names at once
newClasses := []string{"Sorcerer", "Paladin", "Assassin"}
settings.SetClassNames(newClasses)
settings.Save()
## Individual Class Management
Manage classes individually:
settings, _ := control.Get(db)
// Set individual class names
settings.SetClassName(1, "Wizard")
settings.SetClassName(2, "Knight")
settings.SetClassName(3, "Rogue")
settings.Save()
// Validate class names
if settings.IsValidClassName("Wizard") {
fmt.Println("Wizard is a valid class")
}
// Get class number by name
classNum := settings.GetClassNumber("Knight")
fmt.Printf("Knight is class number: %d\n", classNum)
## Class System Integration
Use class settings for player creation and validation:
func validatePlayerClass(db *database.DB, className string) bool {
settings, err := control.Get(db)
if err != nil {
return false
}
return settings.IsValidClassName(className)
}
func getAvailableClasses(db *database.DB) []string {
settings, err := control.Get(db)
if err != nil {
return []string{}
}
return settings.GetClassNames()
}
func getClassID(db *database.DB, className string) int {
settings, err := control.Get(db)
if err != nil {
return 0
}
return settings.GetClassNumber(className)
}
# Administrative Features
## Admin Contact Information
Manage administrator contact information:
settings, _ := control.Get(db)
// Check if admin email is configured
if settings.HasAdminEmail() {
fmt.Printf("Admin contact: %s\n", settings.AdminEmail)
} else {
fmt.Println("No admin email configured")
settings.AdminEmail = "admin@mygame.com"
settings.Save()
}
## Configuration Validation
Validate all control settings:
func validateControlSettings(db *database.DB) []string {
settings, err := control.Get(db)
if err != nil {
return []string{"Failed to load control settings"}
}
var issues []string
// Check world size
if !settings.IsWorldSizeValid() {
issues = append(issues, "Invalid world size")
}
// Check admin email
if !settings.HasAdminEmail() {
issues = append(issues, "No admin email configured")
}
// Check class names
classes := settings.GetClassNames()
if len(classes) == 0 {
issues = append(issues, "No player classes configured")
}
return issues
}
# Game Logic Integration
## Coordinate Validation
Use control settings for game coordinate validation:
func validatePlayerMovement(db *database.DB, newX, newY int) bool {
settings, err := control.Get(db)
if err != nil {
return false
}
return settings.IsWithinWorldBounds(newX, newY)
}
## Registration System
Integrate with player registration:
func canRegisterNewPlayer(db *database.DB) bool {
settings, err := control.Get(db)
if err != nil {
return false
}
return settings.IsOpen()
}
func getRegistrationMessage(db *database.DB) string {
settings, err := control.Get(db)
if err != nil {
return "Unable to check registration status"
}
if settings.IsOpen() {
classes := settings.GetClassNames()
return fmt.Sprintf("Welcome! Choose from these classes: %v", classes)
} else {
return "Registration is currently closed"
}
}
# Configuration Management
## Backup and Restore
Backup control settings:
func backupControlSettings(db *database.DB) (*control.Control, error) {
return control.Get(db)
}
func restoreControlSettings(db *database.DB, backup *control.Control) error {
settings, err := control.Get(db)
if err != nil {
return err
}
settings.WorldSize = backup.WorldSize
settings.Open = backup.Open
settings.AdminEmail = backup.AdminEmail
settings.Class1Name = backup.Class1Name
settings.Class2Name = backup.Class2Name
settings.Class3Name = backup.Class3Name
return settings.Save()
}
## Default Settings
Reset to default configuration:
func resetToDefaults(db *database.DB) error {
settings, err := control.Get(db)
if err != nil {
return err
}
settings.WorldSize = 250
settings.SetOpen(true)
settings.AdminEmail = ""
settings.SetClassNames([]string{"Mage", "Warrior", "Paladin"})
return settings.Save()
}
# Performance Considerations
## Caching Settings
Since control settings rarely change, consider caching:
var controlCache *control.Control
var cacheTime time.Time
func getCachedControlSettings(db *database.DB) (*control.Control, error) {
// Cache for 5 minutes
if controlCache != nil && time.Since(cacheTime) < 5*time.Minute {
return controlCache, nil
}
settings, err := control.Get(db)
if err != nil {
return nil, err
}
controlCache = settings
cacheTime = time.Now()
return settings, nil
}
## Batch Updates
Update multiple settings efficiently:
func updateGameConfiguration(db *database.DB, worldSize int, isOpen bool,
adminEmail string, classes []string) error {
settings, err := control.Get(db)
if err != nil {
return err
}
// Update all settings
settings.WorldSize = worldSize
settings.SetOpen(isOpen)
settings.AdminEmail = adminEmail
settings.SetClassNames(classes)
// Single save operation
return settings.Save()
}
# Error Handling
Common error scenarios and handling:
settings, err := control.Get(db)
if err != nil {
// Handle database connection issues or missing control record
log.Printf("Failed to load control settings: %v", err)
return
}
// Validate before using
if !settings.IsWorldSizeValid() {
log.Println("Warning: Invalid world size detected")
// Could reset to default or reject changes
}
// Save with error handling
if err := settings.Save(); err != nil {
log.Printf("Failed to save control settings: %v", err)
// Could retry or alert administrator
}
The control package provides a centralized way to manage all global game settings through a single, persistent record that can be easily modified and validated.
*/
package control