Player System
The player system (internal/player
) provides comprehensive player character management for the EQ2Go server emulator. This system is converted from the original C++ EQ2EMu Player implementation with modern Go concurrency patterns and clean architecture principles.
Overview
The player system manages all aspects of player characters including:
- Character Data: Basic character information, stats, appearance
- Experience: Adventure and tradeskill XP, vitality, debt recovery
- Skills: Skill progression, bonuses, and management
- Spells: Spell book, casting, maintained effects, passive spells
- Combat: Auto-attack, combat state, weapon handling
- Quests: Quest tracking, progress, completion, rewards
- Social: Friends, ignore lists, guild membership
- Economy: Currency management, trading, banking
- Movement: Position tracking, spawn visibility, zone transfers
- Character Flags: Various character state flags and preferences
- History: Character history tracking and events
- Items: Inventory, equipment, appearance items
- Housing: House ownership, vault access
Architecture
Core Components
Player - Main player character struct extending Entity
PlayerInfo - Detailed character information for serialization
PlayerManager - Multi-player management and coordination
PlayerControlFlags - Character flag state management
CharacterInstances - Instance lockout tracking
Key Files
player.go
- Core Player struct and basic functionalityplayer_info.go
- PlayerInfo struct for character sheet datacharacter_flags.go
- Character flag managementcurrency.go
- Coin and currency handlingexperience.go
- XP, leveling, and vitality systemscombat.go
- Combat mechanics and processingquest_management.go
- Quest system integrationspell_management.go
- Spell book and casting managementskill_management.go
- Skill system integrationspawn_management.go
- Spawn visibility and trackingmanager.go
- Multi-player management systeminterfaces.go
- System integration interfacesconstants.go
- All character flag and system constantstypes.go
- Data structures and type definitions
Player Creation
// Create a new player
player := player.NewPlayer()
// Set basic information
player.SetCharacterID(12345)
player.SetName("TestPlayer")
player.SetLevel(10)
player.SetClass(1) // Fighter
player.SetRace(0) // Human
// Initialize player info
info := player.GetPlayerInfo()
info.SetBindZone(1)
info.SetHouseZone(0)
Character Flags
The system supports all EverQuest II character flags:
// Set character flags
player.SetCharacterFlag(player.CF_ANONYMOUS)
player.SetCharacterFlag(player.CF_LFG)
player.ResetCharacterFlag(player.CF_AFK)
// Check flags
if player.GetCharacterFlag(player.CF_ROLEPLAYING) {
// Handle roleplaying state
}
Available Flags
- CF_COMBAT_EXPERIENCE_ENABLED - Adventure XP enabled
- CF_QUEST_EXPERIENCE_ENABLED - Tradeskill XP enabled
- CF_ANONYMOUS - Anonymous mode
- CF_ROLEPLAYING - Roleplaying flag
- CF_AFK - Away from keyboard
- CF_LFG - Looking for group
- CF_LFW - Looking for work
- CF_HIDE_HOOD/CF_HIDE_HELM - Hide equipment
- CF_ALLOW_DUEL_INVITES - Allow duel invites
- CF_ALLOW_TRADE_INVITES - Allow trade invites
- CF_ALLOW_GROUP_INVITES - Allow group invites
- And many more...
Experience System
// Add adventure XP
if player.AddXP(1000) {
// Player may have leveled up
if player.GetLevel() > oldLevel {
// Handle level up
}
}
// Add tradeskill XP
player.AddTSXP(500)
// Check XP status
if player.AdventureXPEnabled() {
currentXP := player.GetXP()
neededXP := player.GetNeededXP()
}
// Calculate XP from kills
victim := &entity.Spawn{...}
xpReward := player.CalculateXP(victim)
Currency Management
// Add coins
player.AddCoins(10000) // Add 1 gold
// Remove coins (with validation)
if player.RemoveCoins(5000) {
// Transaction successful
}
// Check coin amounts
copper := player.GetCoinsCopper()
silver := player.GetCoinsSilver()
gold := player.GetCoinsGold()
plat := player.GetCoinsPlat()
// Validate sufficient funds
if player.HasCoins(1000) {
// Player can afford the cost
}
Combat System
// Enter combat
player.InCombat(true, false) // Melee combat
// Enter ranged combat
player.InCombat(true, true) // Ranged combat
// Exit combat
player.StopCombat(0) // Stop all combat
// Process combat (called periodically)
player.ProcessCombat()
// Check combat state
if player.GetInfoStruct().GetEngageCommands() != 0 {
// Player is in combat
}
Spell Management
// Add spell to spell book
player.AddSpellBookEntry(spellID, tier, slot, spellType, timer, true)
// Check if player has spell
if player.HasSpell(spellID, tier, false, false) {
// Player has the spell
}
// Get spell tier
tier := player.GetSpellTier(spellID)
// Lock/unlock spells
player.LockAllSpells()
player.UnlockAllSpells(true, nil)
// Manage passive spells
player.AddPassiveSpell(spellID, tier)
player.ApplyPassiveSpells()
Quest Integration
// Get active quest
quest := player.GetQuest(questID)
// Check quest completion
if player.HasQuestBeenCompleted(questID) {
count := player.GetQuestCompletedCount(questID)
}
// Update quest progress
player.SetStepComplete(questID, stepID)
player.AddStepProgress(questID, stepID, progress)
// Check quest requirements
if player.CanReceiveQuest(questID, nil) {
// Player can accept quest
}
Social Features
// Manage friends
player.AddFriend("FriendName", true)
if player.IsFriend("SomeName") {
// Handle friend interaction
}
// Manage ignore list
player.AddIgnore("PlayerName", true)
if player.IsIgnored("SomeName") {
// Player is ignored
}
// Get social lists
friends := player.GetFriends()
ignored := player.GetIgnoredPlayers()
Spawn Management
// Check spawn visibility
if player.ShouldSendSpawn(spawn) {
// Send spawn to player
player.SetSpawnSentState(spawn, player.SPAWN_STATE_SENDING)
}
// Get spawn by player index
spawn := player.GetSpawnByIndex(index)
// Remove spawn from player view
player.RemoveSpawn(spawn, false)
// Process spawn updates
player.CheckSpawnStateQueue()
Player Manager
// Create manager
config := player.ManagerConfig{
MaxPlayers: 1000,
SaveInterval: 5 * time.Minute,
StatsInterval: 1 * time.Minute,
EnableValidation: true,
EnableEvents: true,
EnableStatistics: true,
}
manager := player.NewManager(config)
// Start manager
manager.Start()
// Add player
err := manager.AddPlayer(player)
// Get players
allPlayers := manager.GetAllPlayers()
zonePlayers := manager.GetPlayersInZone(zoneID)
player := manager.GetPlayerByName("PlayerName")
// Send messages
manager.SendToAll(message)
manager.SendToZone(zoneID, message)
// Get statistics
stats := manager.GetPlayerStats()
Database Integration
The system provides interfaces for database operations:
type PlayerDatabase interface {
LoadPlayer(characterID int32) (*Player, error)
SavePlayer(player *Player) error
DeletePlayer(characterID int32) error
LoadPlayerQuests(characterID int32) ([]*quests.Quest, error)
SavePlayerQuests(characterID int32, quests []*quests.Quest) error
// ... more methods
}
Event System
type PlayerEventHandler interface {
OnPlayerLogin(player *Player) error
OnPlayerLogout(player *Player) error
OnPlayerDeath(player *Player, killer *entity.Entity) error
OnPlayerLevelUp(player *Player, newLevel int8) error
// ... more events
}
// Register event handler
manager.AddEventHandler(myHandler)
Thread Safety
All player operations are thread-safe using appropriate synchronization:
- RWMutex for read-heavy operations (spawn maps, quest lists)
- Atomic operations for simple flags and counters
- Channel-based communication for background processing
- Proper lock ordering to prevent deadlocks
Integration with Other Systems
The player system integrates with:
- Entity System - Players extend entities for combat capabilities
- Spell System - Complete spell casting and effect management
- Quest System - Quest tracking and progression
- Skill System - Skill advancement and bonuses
- Faction System - Reputation and standings
- Title System - Character titles and achievements
- Trade System - Player-to-player trading
- Housing System - House ownership and access
Performance Considerations
- Efficient spawn tracking with hash maps for O(1) lookups
- Periodic processing batched for better performance
- Memory-efficient data structures with proper cleanup
- Background save operations to avoid blocking gameplay
- Statistics collection with minimal overhead
Migration from C++
This Go implementation maintains compatibility with the original C++ EQ2EMu player system while providing:
- Modern concurrency with goroutines and channels
- Better error handling with Go's error interface
- Cleaner architecture with interface-based design
- Improved maintainability with package organization
- Enhanced testing capabilities
TODO Items
The conversion includes TODO comments marking areas for future implementation:
- LUA integration for scripting support
- Advanced packet handling for client communication
- Complete database schema implementation
- Full item system integration
- Group and raid management
- PvP mechanics and flagging
- Mail system implementation
- Appearance system completion
Usage Examples
See the individual file documentation and method comments for detailed usage examples. The system is designed to be used alongside the existing EQ2Go server infrastructure with proper initialization and configuration.