/* Package users is the active record implementation for user accounts in the game. The users package provides comprehensive user management for the game, including authentication, character progression, inventory, equipment, and game state management. It handles all aspects of player accounts from registration to advanced gameplay features. # Basic Usage To retrieve a user by ID: user, err := users.Find(db, 1) if err != nil { log.Fatal(err) } fmt.Printf("User: %s (Level %d)\n", user.Username, user.Level) To find a user by username: user, err := users.ByUsername(db, "playerName") if err != nil { log.Fatal(err) } To find a user by email: user, err := users.ByEmail(db, "player@example.com") if err != nil { log.Fatal(err) } # Creating Users with Builder Pattern The package provides a comprehensive builder for creating new user accounts: ## Basic User Creation user, err := users.NewBuilder(db). WithUsername("newplayer"). WithPassword("hashedPassword"). WithEmail("newplayer@example.com"). WithClassID(1). Create() if err != nil { log.Fatal(err) } fmt.Printf("Created user with ID: %d\n", user.ID) ## Advanced User Creation user, err := users.NewBuilder(db). WithUsername("hero"). WithPassword("secureHash"). WithEmail("hero@example.com"). WithVerified(true). WithClassID(2). WithPosition(100, -50). WithLevel(5). WithGold(500). WithStats(8, 7, 10, 9). // strength, dex, attack, defense WithHP(30, 30). WithMP(20, 20). WithSpells([]string{"1", "3", "5"}). WithTowns([]string{"1", "2"}). AsAdmin(). Create() The builder automatically sets sensible defaults for all fields if not specified. # User Management ## Authentication and Verification user, _ := users.Find(db, userID) // Check verification status if user.IsVerified() { fmt.Println("User email is verified") } // Check authorization levels if user.IsAdmin() { fmt.Println("User has admin privileges") } if user.IsModerator() { fmt.Println("User has moderator privileges") } ## Activity Tracking // Update last online time user.UpdateLastOnline() user.Save() // Get activity information registered := user.RegisteredTime() lastOnline := user.LastOnlineTime() fmt.Printf("Registered: %s\n", registered.Format("Jan 2, 2006")) fmt.Printf("Last online: %s\n", lastOnline.Format("Jan 2 15:04")) # Character Management ## Stats and Progression user, _ := users.Find(db, userID) // Get character stats stats := user.GetStats() fmt.Printf("Level %d: HP %d/%d, MP %d/%d\n", stats["level"], stats["hp"], stats["max_hp"], stats["mp"], stats["max_mp"]) // Update character progression user.Level = 10 user.Exp = 5000 user.MaxHP = 50 user.HP = 50 user.Save() ## Position and Movement // Get current position x, y := user.GetPosition() fmt.Printf("Player at (%d, %d)\n", x, y) // Move player user.SetPosition(newX, newY) user.Currently = "Exploring the forest" user.Save() ## Combat Status if user.IsFighting() { fmt.Printf("Fighting monster ID %d (HP: %d)\n", user.MonsterID, user.MonsterHP) } if user.IsAlive() { fmt.Printf("Player has %d HP remaining\n", user.HP) } # Spell System ## Spell Management user, _ := users.Find(db, userID) // Get known spells spells := user.GetSpellIDs() fmt.Printf("Player knows %d spells: %v\n", len(spells), spells) // Check if player knows a specific spell if user.HasSpell("5") { fmt.Println("Player knows spell 5") } // Learn new spells newSpells := append(spells, "7", "8") user.SetSpellIDs(newSpells) user.Save() ## Spell Integration func castSpell(db *database.DB, userID int, spellID string) error { user, err := users.Find(db, userID) if err != nil { return err } if !user.HasSpell(spellID) { return fmt.Errorf("user doesn't know spell %s", spellID) } // Spell casting logic here... return nil } # Town and Travel System ## Town Visits user, _ := users.Find(db, userID) // Get visited towns towns := user.GetTownIDs() fmt.Printf("Visited %d towns: %v\n", len(towns), towns) // Check if player has visited a town if user.HasVisitedTown("3") { fmt.Println("Player has been to town 3") } // Visit new town visitedTowns := append(towns, "4") user.SetTownIDs(visitedTowns) user.Save() ## Travel Integration func visitTown(db *database.DB, userID int, townID string) error { user, err := users.Find(db, userID) if err != nil { return err } // Add town to visited list if not already there if !user.HasVisitedTown(townID) { towns := user.GetTownIDs() user.SetTownIDs(append(towns, townID)) } // Update position and status // town coordinates would be looked up here user.Currently = fmt.Sprintf("In town %s", townID) return user.Save() } # Equipment System ## Equipment Management user, _ := users.Find(db, userID) // Get all equipment equipment := user.GetEquipment() weapon := equipment["weapon"].(map[string]any) armor := equipment["armor"].(map[string]any) fmt.Printf("Weapon: %s (ID: %d)\n", weapon["name"], weapon["id"]) fmt.Printf("Armor: %s (ID: %d)\n", armor["name"], armor["id"]) // Equip new items user.WeaponID = 15 user.WeaponName = "Dragon Sword" user.ArmorID = 8 user.ArmorName = "Steel Plate" user.Save() # Query Operations ## Level-Based Queries // Get all players at a specific level level5Players, err := users.ByLevel(db, 5) if err != nil { log.Fatal(err) } fmt.Printf("Level 5 players (%d):\n", len(level5Players)) for _, player := range level5Players { fmt.Printf("- %s (EXP: %d)\n", player.Username, player.Exp) } ## Online Status Queries // Get players online in the last hour onlinePlayers, err := users.Online(db, time.Hour) if err != nil { log.Fatal(err) } fmt.Printf("Players online in last hour (%d):\n", len(onlinePlayers)) for _, player := range onlinePlayers { lastSeen := time.Since(player.LastOnlineTime()) fmt.Printf("- %s (last seen %v ago)\n", player.Username, lastSeen) } # Database Schema The users table contains extensive character and game state information: CREATE TABLE users ( id INTEGER PRIMARY KEY AUTOINCREMENT, username TEXT NOT NULL, password TEXT NOT NULL, email TEXT NOT NULL, verified INTEGER NOT NULL DEFAULT 0, token TEXT NOT NULL DEFAULT '', registered INTEGER NOT NULL DEFAULT (unixepoch()), last_online INTEGER NOT NULL DEFAULT (unixepoch()), auth INTEGER NOT NULL DEFAULT 0, x INTEGER NOT NULL DEFAULT 0, y INTEGER NOT NULL DEFAULT 0, class_id INTEGER NOT NULL DEFAULT 0, currently TEXT NOT NULL DEFAULT 'In Town', fighting INTEGER NOT NULL DEFAULT 0, -- Combat state fields monster_id INTEGER NOT NULL DEFAULT 0, monster_hp INTEGER NOT NULL DEFAULT 0, monster_sleep INTEGER NOT NULL DEFAULT 0, monster_immune INTEGER NOT NULL DEFAULT 0, uber_damage INTEGER NOT NULL DEFAULT 0, uber_defense INTEGER NOT NULL DEFAULT 0, -- Character stats hp INTEGER NOT NULL DEFAULT 15, mp INTEGER NOT NULL DEFAULT 0, tp INTEGER NOT NULL DEFAULT 10, max_hp INTEGER NOT NULL DEFAULT 15, max_mp INTEGER NOT NULL DEFAULT 0, max_tp INTEGER NOT NULL DEFAULT 10, level INTEGER NOT NULL DEFAULT 1, gold INTEGER NOT NULL DEFAULT 100, exp INTEGER NOT NULL DEFAULT 0, gold_bonus INTEGER NOT NULL DEFAULT 0, exp_bonus INTEGER NOT NULL DEFAULT 0, strength INTEGER NOT NULL DEFAULT 5, dexterity INTEGER NOT NULL DEFAULT 5, attack INTEGER NOT NULL DEFAULT 5, defense INTEGER NOT NULL DEFAULT 5, -- Equipment weapon_id INTEGER NOT NULL DEFAULT 0, armor_id INTEGER NOT NULL DEFAULT 0, shield_id INTEGER NOT NULL DEFAULT 0, slot_1_id INTEGER NOT NULL DEFAULT 0, slot_2_id INTEGER NOT NULL DEFAULT 0, slot_3_id INTEGER NOT NULL DEFAULT 0, weapon_name TEXT NOT NULL DEFAULT '', armor_name TEXT NOT NULL DEFAULT '', shield_name TEXT NOT NULL DEFAULT '', slot_1_name TEXT NOT NULL DEFAULT '', slot_2_name TEXT NOT NULL DEFAULT '', slot_3_name TEXT NOT NULL DEFAULT '', -- Game state drop_code INTEGER NOT NULL DEFAULT 0, spells TEXT NOT NULL DEFAULT '', towns TEXT NOT NULL DEFAULT '' ) # Advanced Features ## Character Progression func levelUpCharacter(user *users.User, newLevel int) { user.Level = newLevel // Increase base stats user.MaxHP += 5 user.HP = user.MaxHP // Full heal on level up user.MaxMP += 2 user.MP = user.MaxMP // Stat bonuses user.Strength++ user.Attack++ user.Defense++ user.Save() } ## Combat Integration func startCombat(user *users.User, monsterID int) error { if user.IsFighting() { return fmt.Errorf("already in combat") } user.Fighting = 1 user.MonsterID = monsterID // monster HP would be looked up from monsters table user.MonsterHP = 50 user.Currently = "Fighting" return user.Save() } func endCombat(user *users.User, won bool) error { user.Fighting = 0 user.MonsterID = 0 user.MonsterHP = 0 user.MonsterSleep = 0 user.MonsterImmune = 0 if won { user.Currently = "Victorious" // Award experience and gold } else { user.Currently = "Defeated" user.HP = 0 // Player defeated } return user.Save() } ## Administrative Functions func promoteUser(db *database.DB, username string, authLevel int) error { user, err := users.ByUsername(db, username) if err != nil { return err } user.Auth = authLevel return user.Save() } func getUsersByAuthLevel(db *database.DB, minAuth int) ([]*users.User, error) { allUsers, err := users.All(db) if err != nil { return nil, err } var authorizedUsers []*users.User for _, user := range allUsers { if user.Auth >= minAuth { authorizedUsers = append(authorizedUsers, user) } } return authorizedUsers, nil } # Performance Considerations The users table is large and frequently accessed. Consider: ## Efficient Queries // Use specific lookups when possible user, _ := users.ByUsername(db, username) // Uses index user, _ := users.ByEmail(db, email) // Uses index // Limit results for admin interfaces onlineUsers, _ := users.Online(db, time.Hour) // Bounded by time levelUsers, _ := users.ByLevel(db, targetLevel) // Bounded by level ## Caching Strategies // Cache frequently accessed user data type UserCache struct { users map[int]*users.User mutex sync.RWMutex } func (c *UserCache) GetUser(db *database.DB, id int) (*users.User, error) { c.mutex.RLock() if user, ok := c.users[id]; ok { c.mutex.RUnlock() return user, nil } c.mutex.RUnlock() user, err := users.Find(db, id) if err != nil { return nil, err } c.mutex.Lock() c.users[id] = user c.mutex.Unlock() return user, nil } # Integration Examples ## Session Management func authenticateUser(db *database.DB, username, password string) (*users.User, error) { user, err := users.ByUsername(db, username) if err != nil { return nil, fmt.Errorf("user not found") } if !user.IsVerified() { return nil, fmt.Errorf("email not verified") } // Verify password (implement password checking) if !verifyPassword(user.Password, password) { return nil, fmt.Errorf("invalid password") } // Update last online user.UpdateLastOnline() user.Save() return user, nil } ## Game State Management func saveGameState(user *users.User, gameData GameState) error { user.X = gameData.X user.Y = gameData.Y user.HP = gameData.HP user.MP = gameData.MP user.Currently = gameData.Status if gameData.InCombat { user.Fighting = 1 user.MonsterID = gameData.MonsterID user.MonsterHP = gameData.MonsterHP } return user.Save() } The users package provides comprehensive player account management with support for all game mechanics including character progression, combat, equipment, spells, and world exploration. */ package users