416 lines
9.6 KiB
Go
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 |